summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boot/dts/Makefile87
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts36
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts17
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts45
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-pcie.dts12
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto.dts18
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts11
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts16
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts36
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-ldo.dts34
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-pcie.dts12
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd.dts156
-rwxr-xr-x[-rw-r--r--]arch/arm/boot/dts/imx6dl.dtsi116
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts36
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts16
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts46
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-pcie.dts12
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts25
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-btwifi.dts11
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-enetirq.dts16
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-hdcp.dts40
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-ldo.dts34
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-pcie.dts12
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-uart.dts23
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd.dts32
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi109
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi383
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi104
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi437
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi154
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts37
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts46
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto.dts87
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts11
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts39
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-ldo.dts42
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd.dts72
-rw-r--r--arch/arm/boot/dts/imx6qp.dtsi69
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-btwifi.dts101
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-csi.dts17
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-ldo.dts26
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-uart.dts23
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts257
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi79
-rw-r--r--arch/arm/boot/dts/imx6sll-evk-btwifi.dts101
-rw-r--r--arch/arm/boot/dts/imx6sll-evk-reva.dts15
-rw-r--r--arch/arm/boot/dts/imx6sll-evk.dts372
-rw-r--r--arch/arm/boot/dts/imx6sll.dtsi93
-rw-r--r--arch/arm/boot/dts/imx6sx-pinfunc.h26
-rw-r--r--arch/arm/boot/dts/imx6sx-sabreauto.dts346
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-btwifi.dts87
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-emmc.dts33
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts31
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-ldo.dts39
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-m4.dts102
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-mqs.dts48
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-reva-ldo.dts21
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dts19
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dtsi408
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi265
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-btwifi-oob.dts10
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-csi.dts18
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-ecspi-slave.dts18
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-ecspi.dts42
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts21
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts43
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk.dtsi227
-rw-r--r--arch/arm/boot/dts/imx6ul-9x9-evk-btwifi-oob.dts10
-rw-r--r--arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6ul-9x9-evk-ldo.dts39
-rw-r--r--arch/arm/boot/dts/imx6ul-9x9-evk.dts813
-rw-r--r--arch/arm/boot/dts/imx6ul-evk-btwifi-oob.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi72
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts401
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi95
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6311-s.dts16
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6311-som.dtsi40
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6x1x-s.dtsi418
-rw-r--r--arch/arm/boot/dts/imx6ul-kontron-n6x1x-som-common.dtsi109
-rw-r--r--arch/arm/boot/dts/imx6ul.dtsi132
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-btwifi-oob.dts10
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts21
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts43
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk.dts17
-rw-r--r--arch/arm/boot/dts/imx6ull-9x9-evk-btwifi-oob.dts10
-rw-r--r--arch/arm/boot/dts/imx6ull-9x9-evk-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6ull-9x9-evk-ldo.dts36
-rw-r--r--arch/arm/boot/dts/imx6ull-9x9-evk.dts813
-rw-r--r--arch/arm/boot/dts/imx6ull-kontron-n6411-s.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-kontron-n6411-som.dtsi40
-rw-r--r--arch/arm/boot/dts/imx6ull.dtsi53
-rw-r--r--arch/arm/boot/dts/imx6ulz-14x14-evk-btwifi.dts16
-rw-r--r--arch/arm/boot/dts/imx6ulz-14x14-evk-emmc.dts25
-rw-r--r--arch/arm/boot/dts/imx6ulz-14x14-evk-gpmi-weim.dts43
-rw-r--r--arch/arm/boot/dts/imx6ulz-14x14-evk.dts17
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-val-sai.dts43
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-val.dts1015
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-epdc.dts7
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-epdc.dtsi60
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dtsi23
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-m4.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-m4.dtsi79
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-mipi-dsi.dts31
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-qspi.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-qspi.dtsi44
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-usd-wifi.dts51
-rw-r--r--arch/arm/boot/dts/imx7d-sdb.dts551
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi209
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi109
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-ft5416.dts15
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-mipi.dts10
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-mipi.dtsi23
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk.dts531
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-emmc.dts26
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-lpuart.dts17
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-mipi.dts25
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-rm68191-qhd.dts13
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-rm68200-wxga.dts13
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-sd1.dts45
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-sensors-to-i2c5.dts21
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb-spi-slave.dts30
-rw-r--r--arch/arm/boot/dts/imx7ulp-evkb.dts39
-rw-r--r--arch/arm/boot/dts/imx7ulp.dtsi277
-rw-r--r--arch/arm/boot/dts/ls1021a-qds.dts19
-rw-r--r--arch/arm/boot/dts/ls1021a-twr.dts15
-rw-r--r--arch/arm/boot/dts/ls1021a.dtsi50
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig180
-rw-r--r--arch/arm/configs/imx_v7_defconfig579
-rw-r--r--arch/arm/configs/lsdk.config88
-rw-r--r--arch/arm/configs/multi_v7_defconfig50
-rw-r--r--arch/arm/configs/multi_v7_lpae.config2
-rw-r--r--arch/arm/configs/multi_v8.config23
-rw-r--r--arch/arm/include/asm/delay.h16
-rw-r--r--arch/arm/include/asm/io.h31
-rw-r--r--arch/arm/include/asm/kvm_mmu.h3
-rw-r--r--arch/arm/include/asm/mach/map.h4
-rw-r--r--arch/arm/include/asm/pgtable.h7
-rw-r--r--arch/arm/kernel/bios32.c44
-rw-r--r--arch/arm/kernel/time.c3
-rw-r--r--arch/arm/mach-imx/Kconfig33
-rw-r--r--arch/arm/mach-imx/Makefile51
-rw-r--r--arch/arm/mach-imx/anatop.c153
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c1407
-rw-r--r--arch/arm/mach-imx/busfreq_ddr3.c772
-rw-r--r--arch/arm/mach-imx/busfreq_lpddr2.c374
-rw-r--r--arch/arm/mach-imx/common.c161
-rw-r--r--arch/arm/mach-imx/common.h77
-rw-r--r--arch/arm/mach-imx/cpu.c45
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c198
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sll.c277
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sx.c260
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6ul.c327
-rw-r--r--arch/arm/mach-imx/cpuidle-imx7d.c390
-rw-r--r--arch/arm/mach-imx/cpuidle.h20
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6.S1103
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6sx.S764
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx7d.S586
-rw-r--r--arch/arm/mach-imx/ddrc.c86
-rw-r--r--arch/arm/mach-imx/gpc.c278
-rw-r--r--arch/arm/mach-imx/gpcv2.c851
-rw-r--r--arch/arm/mach-imx/hardware.h14
-rw-r--r--arch/arm/mach-imx/headsmp.S11
-rw-r--r--arch/arm/mach-imx/imx6sl_low_power_idle.S776
-rw-r--r--arch/arm/mach-imx/imx6sll_low_power_idle.S780
-rw-r--r--arch/arm/mach-imx/imx6sx_low_power_idle.S887
-rw-r--r--arch/arm/mach-imx/imx6ul_low_power_idle.S821
-rw-r--r--arch/arm/mach-imx/imx6ull_low_power_idle.S764
-rw-r--r--arch/arm/mach-imx/imx7d_low_power_idle.S788
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6.S618
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6q.S765
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6sll.S460
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6sx.S492
-rw-r--r--arch/arm/mach-imx/lpddr3_freq_imx.S444
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c73
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c20
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c18
-rw-r--r--arch/arm/mach-imx/mach-imx6ul.c11
-rw-r--r--arch/arm/mach-imx/mach-imx7d.c54
-rw-r--r--arch/arm/mach-imx/mach-imx7ulp.c21
-rw-r--r--arch/arm/mach-imx/mmdc.c6
-rw-r--r--arch/arm/mach-imx/mu.c434
-rw-r--r--arch/arm/mach-imx/mx6.h51
-rw-r--r--arch/arm/mach-imx/mx7.h54
-rw-r--r--arch/arm/mach-imx/mx7ulp.h63
-rw-r--r--arch/arm/mach-imx/mxc.h23
-rw-r--r--arch/arm/mach-imx/platsmp.c32
-rw-r--r--arch/arm/mach-imx/pm-imx6.c995
-rw-r--r--arch/arm/mach-imx/pm-imx7.c1230
-rw-r--r--arch/arm/mach-imx/pm-imx7ulp.c788
-rw-r--r--arch/arm/mach-imx/pm-rpmsg.c353
-rw-r--r--arch/arm/mach-imx/smp_wfe.S110
-rw-r--r--arch/arm/mach-imx/smp_wfe_imx6.S186
-rw-r--r--arch/arm/mach-imx/src.c91
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S526
-rw-r--r--arch/arm/mach-imx/suspend-imx7.S714
-rw-r--r--arch/arm/mach-imx/suspend-imx7ulp.S625
-rw-r--r--arch/arm/mm/dma-mapping.c1
-rw-r--r--arch/arm/mm/ioremap.c7
-rw-r--r--arch/arm/mm/mmu.c9
205 files changed, 34261 insertions, 1321 deletions
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b21b3a64641a..70250bd6f961 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -435,8 +435,18 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-rex-basic.dtb \
imx6dl-riotboard.dtb \
imx6dl-sabreauto.dtb \
+ imx6dl-sabreauto-enetirq.dtb \
+ imx6dl-sabreauto-flexcan1.dtb \
+ imx6dl-sabreauto-ecspi.dtb \
+ imx6dl-sabreauto-gpmi-weim.dtb \
+ imx6dl-sabreauto-pcie.dtb \
imx6dl-sabrelite.dtb \
imx6dl-sabresd.dtb \
+ imx6dl-sabresd-ldo.dtb \
+ imx6dl-sabresd-btwifi.dtb \
+ imx6dl-sabresd-hdcp.dtb \
+ imx6dl-sabresd-enetirq.dtb \
+ imx6dl-sabresd-pcie.dtb \
imx6dl-savageboard.dtb \
imx6dl-ts4900.dtb \
imx6dl-ts7970.dtb \
@@ -514,8 +524,19 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-pistachio.dtb \
imx6q-rex-pro.dtb \
imx6q-sabreauto.dtb \
+ imx6q-sabreauto-enetirq.dtb \
+ imx6q-sabreauto-flexcan1.dtb \
+ imx6q-sabreauto-ecspi.dtb \
+ imx6q-sabreauto-gpmi-weim.dtb \
+ imx6q-sabreauto-pcie.dtb \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb \
+ imx6q-sabresd-ldo.dtb \
+ imx6q-sabresd-btwifi.dtb \
+ imx6q-sabresd-hdcp.dtb \
+ imx6q-sabresd-uart.dtb \
+ imx6q-sabresd-enetirq.dtb \
+ imx6q-sabresd-pcie.dtb \
imx6q-savageboard.dtb \
imx6q-sbc6x.dtb \
imx6q-tbs2910.dtb \
@@ -541,7 +562,13 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6qp-nitrogen6_som2.dtb \
imx6qp-phytec-mira-rdk-nand.dtb \
imx6qp-sabreauto.dtb \
+ imx6qp-sabreauto-flexcan1.dtb \
+ imx6qp-sabreauto-ecspi.dtb \
+ imx6qp-sabreauto-gpmi-weim.dtb \
imx6qp-sabresd.dtb \
+ imx6qp-sabresd-ldo.dtb \
+ imx6qp-sabresd-btwifi.dtb \
+ imx6qp-sabresd-hdcp.dtb \
imx6qp-tx6qp-8037.dtb \
imx6qp-tx6qp-8037-mb7.dtb \
imx6qp-tx6qp-8137.dtb \
@@ -550,21 +577,45 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6qp-zii-rdu2.dtb
dtb-$(CONFIG_SOC_IMX6SL) += \
imx6sl-evk.dtb \
+ imx6sl-evk-ldo.dtb \
+ imx6sl-evk-csi.dtb \
+ imx6sl-evk-uart.dtb \
+ imx6sl-evk-btwifi.dtb \
imx6sl-warp.dtb
dtb-$(CONFIG_SOC_IMX6SLL) += \
- imx6sll-evk.dtb
+ imx6sll-evk.dtb \
+ imx6sll-evk-reva.dtb \
+ imx6sll-evk-btwifi.dtb
dtb-$(CONFIG_SOC_IMX6SX) += \
imx6sx-nitrogen6sx.dtb \
imx6sx-sabreauto.dtb \
imx6sx-sdb-reva.dtb \
+ imx6sx-sdb-reva-ldo.dtb \
imx6sx-sdb-sai.dtb \
imx6sx-sdb.dtb \
+ imx6sx-sdb-ldo.dtb \
+ imx6sx-sdb-emmc.dtb \
+ imx6sx-sdb-lcdif1.dtb \
+ imx6sx-sdb-m4.dtb \
+ imx6sx-sdb-mqs.dtb \
+ imx6sx-sdb-btwifi.dtb \
imx6sx-softing-vining-2000.dtb \
imx6sx-udoo-neo-basic.dtb \
imx6sx-udoo-neo-extended.dtb \
imx6sx-udoo-neo-full.dtb
dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ul-14x14-evk.dtb \
+ imx6ul-14x14-evk-csi.dtb \
+ imx6ul-14x14-evk-emmc.dtb \
+ imx6ul-14x14-evk-btwifi.dtb \
+ imx6ul-14x14-evk-btwifi-oob.dtb \
+ imx6ul-14x14-evk-ecspi-slave.dtb \
+ imx6ul-14x14-evk-ecspi.dtb \
+ imx6ul-14x14-evk-gpmi-weim.dtb \
+ imx6ul-9x9-evk.dtb \
+ imx6ul-9x9-evk-ldo.dtb \
+ imx6ul-9x9-evk-btwifi.dtb \
+ imx6ul-9x9-evk-btwifi-oob.dtb \
imx6ul-ccimx6ulsbcexpress.dtb \
imx6ul-ccimx6ulsbcpro.dtb \
imx6ul-geam.dtb \
@@ -581,12 +632,23 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ul-tx6ul-0011.dtb \
imx6ul-tx6ul-mainboard.dtb \
imx6ull-14x14-evk.dtb \
+ imx6ull-14x14-evk-emmc.dtb \
+ imx6ull-14x14-evk-btwifi.dtb \
+ imx6ull-14x14-evk-btwifi-oob.dtb \
+ imx6ull-14x14-evk-gpmi-weim.dtb \
+ imx6ull-9x9-evk.dtb \
+ imx6ull-9x9-evk-ldo.dtb \
+ imx6ull-9x9-evk-btwifi.dtb \
+ imx6ull-9x9-evk-btwifi-oob.dtb \
imx6ull-colibri-eval-v3.dtb \
imx6ull-colibri-wifi-eval-v3.dtb \
imx6ull-phytec-segin-ff-rdk-nand.dtb \
imx6ull-phytec-segin-ff-rdk-emmc.dtb \
imx6ull-phytec-segin-lc-rdk-nand.dtb \
- imx6ulz-14x14-evk.dtb
+ imx6ulz-14x14-evk.dtb \
+ imx6ulz-14x14-evk-btwifi.dtb \
+ imx6ulz-14x14-evk-gpmi-weim.dtb \
+ imx6ulz-14x14-evk-emmc.dtb
dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-cl-som-imx7.dtb \
imx7d-colibri-emmc-eval-v3.dtb \
@@ -598,15 +660,34 @@ dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-pico-pi.dtb \
imx7d-sbc-imx7.dtb \
imx7d-sdb.dtb \
+ imx7d-sdb-epdc.dtb \
+ imx7d-sdb-mipi-dsi.dtb \
+ imx7d-sdb-gpmi-weim.dtb \
+ imx7d-sdb-m4.dtb \
+ imx7d-sdb-qspi.dtb \
imx7d-sdb-reva.dtb \
imx7d-sdb-sht11.dtb \
+ imx7d-sdb-usd-wifi.dtb \
+ imx7d-12x12-lpddr3-val.dtb \
+ imx7d-12x12-lpddr3-val-sai.dtb \
imx7d-zii-rmu2.dtb \
imx7d-zii-rpu2.dtb \
imx7s-colibri-eval-v3.dtb \
imx7s-mba7.dtb \
imx7s-warp.dtb
dtb-$(CONFIG_SOC_IMX7ULP) += \
- imx7ulp-evk.dtb
+ imx7ulp-evk.dtb \
+ imx7ulp-evk-ft5416.dtb \
+ imx7ulp-evk-mipi.dtb \
+ imx7ulp-evkb.dtb \
+ imx7ulp-evkb-emmc.dtb \
+ imx7ulp-evkb-sd1.dtb \
+ imx7ulp-evkb-spi-slave.dtb \
+ imx7ulp-evkb-sensors-to-i2c5.dtb \
+ imx7ulp-evkb-lpuart.dtb \
+ imx7ulp-evkb-mipi.dtb \
+ imx7ulp-evkb-rm68200-wxga.dtb \
+ imx7ulp-evkb-rm68191-qhd.dtb
dtb-$(CONFIG_SOC_LS1021A) += \
ls1021a-moxa-uc-8410a.dtb \
ls1021a-qds.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts b/arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts
new file mode 100644
index 000000000000..d468a5535657
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+
+
+#include "imx6dl-sabreauto.dts"
+
+&ecspi1 {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&i2c3 {
+ /* pin conflict with ecspi1 */
+ status = "disabled";
+};
+
+&uart3 {
+ /* the uart3 depends on the i2c3, so disable it too. */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts b/arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts
new file mode 100644
index 000000000000..75c798f7616a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2013 Freescale Semiconductor, Inc.
+// Copyright 2019 NXP
+
+#include "imx6dl-sabreauto.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+ <&gpc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,err006687-workaround-present;
+};
+
+&mlb {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto-flexcan1.dts b/arch/arm/boot/dts/imx6dl-sabreauto-flexcan1.dts
new file mode 100644
index 000000000000..f101f7c7b7b0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-flexcan1.dts
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6dl-sabreauto.dts"
+
+&can1{
+ status = "okay";
+};
+
+&fec {
+ /* pin conflict with flexcan1 */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts b/arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts
new file mode 100644
index 000000000000..8990519be861
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+
+
+#include "imx6dl-sabreauto.dts"
+
+&ecspi1 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&gpmi {
+ status = "okay";
+};
+
+&i2c3 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&uart3 {
+ /* pin conflict with gpmi and weim */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&weim {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto-pcie.dts b/arch/arm/boot/dts/imx6dl-sabreauto-pcie.dts
new file mode 100644
index 000000000000..88fc15b1a9de
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-pcie.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+/dts-v1/;
+
+#include "imx6dl-sabreauto.dts"
+
+&pcie {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto.dts b/arch/arm/boot/dts/imx6dl-sabreauto.dts
index ff3283c83a39..be38a92c6a90 100644
--- a/arch/arm/boot/dts/imx6dl-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6dl-sabreauto.dts
@@ -26,3 +26,21 @@
396000 1175000
>;
};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu1-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu1-di1";
+ };
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts
new file mode 100644
index 000000000000..ac57fffe74c7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6dl-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts b/arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts
new file mode 100644
index 000000000000..5aee10ff88b9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+// Copyright 2019 NXP
+
+#include "imx6dl-sabresd.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 0x4>, <&gpc 0 119 0x4>;
+ fsl,err006687-workaround-present;
+};
+
+&i2c3 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts b/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts
new file mode 100644
index 000000000000..2c7f04456cbb
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6dl-sabresd.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
new file mode 100644
index 000000000000..e5c623d85e4e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6dl-sabresd.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-pcie.dts b/arch/arm/boot/dts/imx6dl-sabresd-pcie.dts
new file mode 100644
index 000000000000..c57558c815d9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-pcie.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+/dts-v1/;
+
+#include "imx6dl-sabresd.dts"
+
+&pcie {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd.dts b/arch/arm/boot/dts/imx6dl-sabresd.dts
index cd6bbf22a16f..7b253d13b02d 100644
--- a/arch/arm/boot/dts/imx6dl-sabresd.dts
+++ b/arch/arm/boot/dts/imx6dl-sabresd.dts
@@ -12,7 +12,163 @@
compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
};
+&battery {
+ offset-charger = <1485>;
+ offset-discharger = <1464>;
+ offset-usb-charger = <1285>;
+};
+
+&iomuxc {
+ epdc {
+ pinctrl_epdc_elan_touch: epdc_elan_touch_grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x80000000
+ MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x80000000
+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000
+ >;
+ };
+
+ pinctrl_epdc_0: epdcgrp-0 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A16__EPDC_DATA00 0x80000000
+ MX6QDL_PAD_EIM_DA10__EPDC_DATA01 0x80000000
+ MX6QDL_PAD_EIM_DA12__EPDC_DATA02 0x80000000
+ MX6QDL_PAD_EIM_DA11__EPDC_DATA03 0x80000000
+ MX6QDL_PAD_EIM_LBA__EPDC_DATA04 0x80000000
+ MX6QDL_PAD_EIM_EB2__EPDC_DATA05 0x80000000
+ MX6QDL_PAD_EIM_CS0__EPDC_DATA06 0x80000000
+ MX6QDL_PAD_EIM_RW__EPDC_DATA07 0x80000000
+ MX6QDL_PAD_EIM_A21__EPDC_GDCLK 0x80000000
+ MX6QDL_PAD_EIM_A22__EPDC_GDSP 0x80000000
+ MX6QDL_PAD_EIM_A23__EPDC_GDOE 0x80000000
+ MX6QDL_PAD_EIM_A24__EPDC_GDRL 0x80000000
+ MX6QDL_PAD_EIM_D31__EPDC_SDCLK_P 0x80000000
+ MX6QDL_PAD_EIM_D27__EPDC_SDOE 0x80000000
+ MX6QDL_PAD_EIM_DA1__EPDC_SDLE 0x80000000
+ MX6QDL_PAD_EIM_EB1__EPDC_SDSHR 0x80000000
+ MX6QDL_PAD_EIM_DA2__EPDC_BDR0 0x80000000
+ MX6QDL_PAD_EIM_DA4__EPDC_SDCE0 0x80000000
+ MX6QDL_PAD_EIM_DA5__EPDC_SDCE1 0x80000000
+ MX6QDL_PAD_EIM_DA6__EPDC_SDCE2 0x80000000
+ >;
+ };
+ };
+};
+
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc_0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
+&i2c3 {
+ elan@10 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc_elan_touch>;
+ compatible = "elan,elan-touch";
+ reg = <0x10>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+ gpio_elan_cs = <&gpio2 18 0>;
+ gpio_elan_rst = <&gpio3 8 0>;
+ gpio_intr = <&gpio3 28 0>;
+ status = "okay";
+ };
+
+ max17135@48 {
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ vneg_pwrup = <1>;
+ gvee_pwrup = <1>;
+ vpos_pwrup = <2>;
+ gvdd_pwrup = <1>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <1>;
+ vneg_pwrdn = <1>;
+ SENSOR-supply = <&reg_sensors>;
+ gpio_pmic_pwrgood = <&gpio2 21 0>;
+ gpio_pmic_vcom_ctrl = <&gpio3 17 0>;
+ gpio_pmic_wakeup = <&gpio3 20 0>;
+ gpio_pmic_v3p3 = <&gpio2 20 0>;
+ gpio_pmic_intr = <&gpio2 25 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* Real max: -500000 */
+ regulator-max-microvolt = <4325000>;
+ /* Real min: -4325000 */
+ regulator-min-microvolt = <500000>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
+};
+
&ipu1_csi1_from_ipu1_csi1_mux {
clock-lanes = <0>;
data-lanes = <1 2>;
};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu1-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu1-di1";
+ };
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 2ed10310a7b7..845adeed6785 100644..100755
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -38,9 +38,13 @@
<&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
<&clks IMX6QDL_CLK_STEP>,
<&clks IMX6QDL_CLK_PLL1_SW>,
- <&clks IMX6QDL_CLK_PLL1_SYS>;
+ <&clks IMX6QDL_CLK_PLL1_SYS>,
+ <&clks IMX6QDL_CLK_PLL1>,
+ <&clks IMX6QDL_PLL1_BYPASS>,
+ <&clks IMX6QDL_PLL1_BYPASS_SRC>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1",
+ "pll1_bypass", "pll1_bypass_src";
arm-supply = <&reg_arm>;
pu-supply = <&reg_pu>;
soc-supply = <&reg_soc>;
@@ -77,30 +81,105 @@
};
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
soc {
- ocram: sram@900000 {
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6QDL_CLK_PLL2_BUS>, <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+ <&clks IMX6QDL_CLK_PLL2_198M>, <&clks IMX6QDL_CLK_ARM>,
+ <&clks IMX6QDL_CLK_PLL3_USB_OTG>, <&clks IMX6QDL_CLK_PERIPH>,
+ <&clks IMX6QDL_CLK_PERIPH_PRE>, <&clks IMX6QDL_CLK_PERIPH_CLK2>,
+ <&clks IMX6QDL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6QDL_CLK_OSC>,
+ <&clks IMX6QDL_CLK_AXI_ALT_SEL>, <&clks IMX6QDL_CLK_AXI_SEL> ,
+ <&clks IMX6QDL_CLK_PLL3_PFD1_540M>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm",
+ "pll3_usb_otg", "periph", "periph_pre", "periph_clk2",
+ "periph_clk2_sel", "osc", "axi_alt_sel", "axi_sel",
+ "pll3_pfd1_540m";
+ interrupts = <0 107 0x4>, <0 112 0x4>;
+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ ocram: sram@905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x905000 0x1B000>;
clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
+ ocram_optee: sram@918000 {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x918000 0x8000>;
+ overw_reg = <&ocram 0x905000 0x13000>;
+ };
+
+ gpu: gpu@00130000 {
+ compatible = "fsl,imx6dl-gpu", "fsl,imx6q-gpu";
+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
+ <0x10000000 0x0>, <0x0 0x8000000>;
+ reg-names = "iobase_3d", "iobase_2d",
+ "phys_baseaddr", "contiguous_mem";
+ interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>,
+ <0 10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_3d", "irq_2d";
+ clocks = <&clks IMX6QDL_CLK_OPENVG_AXI>, <&clks IMX6QDL_CLK_GPU3D_AXI>,
+ <&clks IMX6QDL_CLK_GPU2D_CORE>, <&clks IMX6QDL_CLK_GPU3D_CORE>,
+ <&clks IMX6QDL_CLK_DUMMY>;
+ clock-names = "gpu2d_axi_clk", "gpu3d_axi_clk",
+ "gpu2d_clk", "gpu3d_clk",
+ "gpu3d_shader_clk";
+ resets = <&src 0>, <&src 3>;
+ reset-names = "gpu3d", "gpu2d";
+ power-domains = <&pd_pu>;
+ };
+
aips1: aips-bus@2000000 {
iomuxc: iomuxc@20e0000 {
compatible = "fsl,imx6dl-iomuxc";
};
pxp: pxp@20f0000 {
- reg = <0x020f0000 0x4000>;
+ compatible = "fsl,imx6dl-pxp-dma";
+ reg = <0x20f0000 0x4000>;
interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_IPU2>, <&clks IMX6QDL_CLK_DUMMY>;
+ clock-names = "pxp-axi", "disp-axi";
+ status = "disabled";
};
epdc: epdc@20f4000 {
- reg = <0x020f4000 0x4000>;
+ compatible = "fsl,imx6dl-epdc";
+ reg = <0x20f4000 0x4000>;
interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_IPU2>, <&clks IMX6QDL_CLK_IPU2_DI1>;
+ clock-names = "epdc_axi", "epdc_pix";
};
};
aips2: aips-bus@2100000 {
+ mipi_dsi: mipi@21e0000 {
+ compatible = "fsl,imx6dl-mipi-dsi";
+ reg = <0x21e0000 0x4000>;
+ interrupts = <0 102 0x4>;
+ gpr = <&gpr>;
+ clocks = <&clks IMX6QDL_CLK_HSI_TX>, <&clks IMX6QDL_CLK_VIDEO_27M>;
+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
+ status = "disabled";
+ };
+
i2c4: i2c@21f8000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -124,6 +203,12 @@
};
};
+&dcic2 {
+ clocks = <&clks IMX6QDL_CLK_DCIC1 >,
+ <&clks IMX6QDL_CLK_DCIC2>; /* DCIC2 depend on DCIC1 clock in imx6dl*/
+ clock-names = "dcic", "disp-axi";
+};
+
&gpio1 {
gpio-ranges = <&iomuxc 0 131 2>, <&iomuxc 2 137 8>, <&iomuxc 10 189 2>,
<&iomuxc 12 194 1>, <&iomuxc 13 193 1>, <&iomuxc 14 192 1>,
@@ -302,12 +387,19 @@
};
&ldb {
- clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+ compatible = "fsl,imx6dl-ldb", "fsl,imx53-ldb";
+ clocks = <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>,
<&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
- <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
- clock-names = "di0_pll", "di1_pll",
+ <&clks IMX6QDL_CLK_IPU2_DI0_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_3_5>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_3_5>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_7>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_7>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_SEL>;
+ clock-names = "ldb_di0", "ldb_di1",
"di0_sel", "di1_sel",
- "di0", "di1";
+ "di2_sel",
+ "ldb_di0_div_3_5", "ldb_di1_div_3_5",
+ "ldb_di0_div_7", "ldb_di1_div_7",
+ "ldb_di0_div_sel", "ldb_di1_div_sel";
};
&mipi_csi {
@@ -389,3 +481,7 @@
&vpu {
compatible = "fsl,imx6dl-vpu", "cnm,coda960";
};
+
+&vpu_fsl {
+ iramsize = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts b/arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts
new file mode 100644
index 000000000000..44a31e56d8f2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+
+#include "imx6q-sabreauto.dts"
+
+&ecspi1 {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&i2c3 {
+ /* pin conflict with ecspi1 */
+ status = "disabled";
+};
+
+&uart3 {
+ /* the uart3 depends on the i2c3, so disable it too. */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ /* max7310_c on i2c3 is gone */
+ status = "okay";
+ dr_mode = "peripheral";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts b/arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts
new file mode 100644
index 000000000000..04351f1feed4
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2019 NXP
+
+#include "imx6q-sabreauto.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+ <&gpc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,err006687-workaround-present;
+};
+
+&mlb {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto-flexcan1.dts b/arch/arm/boot/dts/imx6q-sabreauto-flexcan1.dts
new file mode 100644
index 000000000000..71dd58944801
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-flexcan1.dts
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6q-sabreauto.dts"
+
+&can1{
+ status = "okay";
+};
+
+&fec {
+ /* pin conflict with flexcan1 */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts b/arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts
new file mode 100644
index 000000000000..bbeb10557cbc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+
+
+#include "imx6q-sabreauto.dts"
+
+&ecspi1 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&gpmi {
+ status = "okay";
+};
+
+&i2c3 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&uart3 {
+ /* pin conflict with gpmi and weim */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ /* max7310_c on i2c3 is gone */
+ status = "okay";
+ dr_mode = "peripheral";
+};
+
+&weim {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto-pcie.dts b/arch/arm/boot/dts/imx6q-sabreauto-pcie.dts
new file mode 100644
index 000000000000..769a2cf4a6ac
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-pcie.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+/dts-v1/;
+
+#include "imx6q-sabreauto.dts"
+
+&pcie {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
index 6e981a3e0a83..e6493858c30e 100644
--- a/arch/arm/boot/dts/imx6q-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -13,6 +13,31 @@
compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
};
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb3 {
+ status = "okay";
+};
+
+&mxcfb4 {
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts
new file mode 100644
index 000000000000..5f55b7df2942
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6q-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-sabresd-enetirq.dts b/arch/arm/boot/dts/imx6q-sabresd-enetirq.dts
new file mode 100644
index 000000000000..4c9e62779c47
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-enetirq.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+// Copyright 2019 NXP
+
+#include "imx6q-sabresd.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 0x4>, <&gpc 0 119 0x4>;
+ fsl,err006687-workaround-present;
+};
+
+&i2c3 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts b/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts
new file mode 100644
index 000000000000..3116e3efb835
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012-2014 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
+ */
+
+#include "imx6q-sabresd.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-ldo.dts b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
new file mode 100644
index 000000000000..8363302dca35
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6q-sabresd.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-pcie.dts b/arch/arm/boot/dts/imx6q-sabresd-pcie.dts
new file mode 100644
index 000000000000..2ff88f6a1d52
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-pcie.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+/dts-v1/;
+
+#include "imx6q-sabresd.dts"
+
+&pcie {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-uart.dts b/arch/arm/boot/dts/imx6q-sabresd-uart.dts
new file mode 100644
index 000000000000..800479da5941
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-uart.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6q-sabresd.dts"
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5_1>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
+};
+
+&ecspi1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index eec944673c0b..ca8c7d1a29cb 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -13,6 +13,38 @@
compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
};
+&battery {
+ offset-charger = <1900>;
+ offset-discharger = <1694>;
+ offset-usb-charger = <1685>;
+};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb3 {
+ status = "okay";
+};
+
+&mxcfb4 {
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index d038f4117024..2d3e137fc1fc 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -43,9 +43,13 @@
<&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
<&clks IMX6QDL_CLK_STEP>,
<&clks IMX6QDL_CLK_PLL1_SW>,
- <&clks IMX6QDL_CLK_PLL1_SYS>;
+ <&clks IMX6QDL_CLK_PLL1_SYS>,
+ <&clks IMX6QDL_CLK_PLL1>,
+ <&clks IMX6QDL_PLL1_BYPASS>,
+ <&clks IMX6QDL_PLL1_BYPASS_SRC>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1",
+ "pll1_bypass", "pll1_bypass_src";
arm-supply = <&reg_arm>;
pu-supply = <&reg_pu>;
soc-supply = <&reg_soc>;
@@ -154,13 +158,44 @@
};
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
soc {
- ocram: sram@900000 {
+ busfreq: busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg",
+ "periph", "periph_pre", "periph_clk2", "periph_clk2_sel", "osc";
+ interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>;
+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3";
+ fsl,max_ddr_freq = <528000000>;
+ };
+
+ ocram: sram@905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x40000>;
+ reg = <0x905000 0x3B000>;
clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
+ ocram_optee: sram@938000 {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x938000 0x8000>;
+ overw_reg = <&ocram 0x905000 0x33000>;
+ };
+
aips-bus@2000000 { /* AIPS1 */
spba-bus@2000000 {
ecspi5: spi@2018000 {
@@ -172,7 +207,7 @@
clocks = <&clks IMX6Q_CLK_ECSPI5>,
<&clks IMX6Q_CLK_ECSPI5>;
clock-names = "ipg", "per";
- dmas = <&sdma 11 8 1>, <&sdma 12 8 2>;
+ dmas = <&sdma 11 7 1>, <&sdma 12 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -183,6 +218,18 @@
};
};
+ aips-bus@2100000 { /* AIPS2 */
+ mipi_dsi: mipi@21e0000 {
+ compatible = "fsl,imx6q-mipi-dsi";
+ reg = <0x21e0000 0x4000>;
+ interrupts = <0 102 0x4>;
+ gpr = <&gpr>;
+ clocks = <&clks IMX6QDL_CLK_HSI_TX>, <&clks IMX6QDL_CLK_VIDEO_27M>;
+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
+ status = "disabled";
+ };
+ };
+
sata: sata@2200000 {
compatible = "fsl,imx6q-ahci";
reg = <0x02200000 0x4000>;
@@ -203,6 +250,30 @@
clock-names = "bus", "core";
power-domains = <&pd_pu>;
#cooling-cells = <2>;
+ status = "disabled";
+ };
+
+ gpu: gpu@00130000 {
+ compatible = "fsl,imx6q-gpu";
+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
+ <0x02204000 0x4000>, <0x10000000 0x0>,
+ <0x0 0x8000000>;
+ reg-names = "iobase_3d", "iobase_2d",
+ "iobase_vg", "phys_baseaddr",
+ "contiguous_mem";
+ interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>,
+ <0 10 IRQ_TYPE_LEVEL_HIGH>,
+ <0 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_3d", "irq_2d", "irq_vg";
+ clocks = <&clks IMX6QDL_CLK_GPU2D_AXI>, <&clks IMX6QDL_CLK_OPENVG_AXI>,
+ <&clks IMX6QDL_CLK_GPU3D_AXI>, <&clks IMX6QDL_CLK_GPU2D_CORE>,
+ <&clks IMX6QDL_CLK_GPU3D_CORE>, <&clks IMX6QDL_CLK_GPU3D_SHADER>;
+ clock-names = "gpu2d_axi_clk", "openvg_axi_clk",
+ "gpu3d_axi_clk", "gpu2d_clk",
+ "gpu3d_clk", "gpu3d_shader_clk";
+ resets = <&src 0>, <&src 3>, <&src 3>;
+ reset-names = "gpu3d", "gpu2d", "gpuvg";
+ power-domains = <&pd_pu>;
};
ipu2: ipu@2800000 {
@@ -214,9 +285,17 @@
<0 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_IPU2>,
<&clks IMX6QDL_CLK_IPU2_DI0>,
- <&clks IMX6QDL_CLK_IPU2_DI1>;
- clock-names = "bus", "di0", "di1";
+ <&clks IMX6QDL_CLK_IPU2_DI1>,
+ <&clks IMX6QDL_CLK_IPU2_DI0_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0>,
+ <&clks IMX6QDL_CLK_LDB_DI1>;
+ clock-names = "bus",
+ "di0", "di1",
+ "di0_sel", "di1_sel",
+ "ldb_di0", "ldb_di1";
resets = <&src 4>;
+ bypass_reset = <0>;
ipu2_csi0: port@0 {
reg = <0>;
@@ -429,13 +508,19 @@
};
&ldb {
- clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+ compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb";
+ clocks = <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>,
<&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
<&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
- <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
- clock-names = "di0_pll", "di1_pll",
- "di0_sel", "di1_sel", "di2_sel", "di3_sel",
- "di0", "di1";
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_3_5>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_3_5>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_7>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_7>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_SEL>;
+ clock-names = "ldb_di0", "ldb_di1",
+ "di0_sel", "di1_sel",
+ "di2_sel", "di3_sel",
+ "ldb_di0_div_3_5", "ldb_di1_div_3_5",
+ "ldb_di0_div_7", "ldb_di1_div_7",
+ "ldb_di0_div_sel", "ldb_di1_div_sel";
lvds-channel@0 {
port@2 {
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index cf628465cd0a..e213ae47e441 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -11,7 +11,14 @@
stdout-path = &uart4;
};
- memory@10000000 {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
+ memory: memory@10000000 {
device_type = "memory";
reg = <0x10000000 0x80000000>;
};
@@ -84,6 +91,14 @@
regulator-always-on;
};
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
reg_usb_h1_vbus: regulator-usb-h1-vbus {
compatible = "regulator-fixed";
regulator-name = "usb_h1_vbus";
@@ -121,26 +136,113 @@
vin-supply = <&reg_can_en>;
};
+ reg_si4763_vio1: regulator@3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_vio2: regulator@4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_vd: regulator@5 {
+ compatible = "regulator-fixed";
+ regulator-name = "vd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_va: regulator@6 {
+ compatible = "regulator-fixed";
+ regulator-name = "va";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_hdmi: regulator-hdmi {
+ compatible = "regulator-fixed";
+ regulator-name = "hdmi-5v-supply";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ hdmi-5v-supply = <&swbst_reg>;
+ };
+
+ 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 = <24>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb3: fb@2 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "lcd";
+ interface_pix_fmt = "RGB565";
+ 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 = "ldb";
+ interface_pix_fmt = "RGB666";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
sound-cs42888 {
compatible = "fsl,imx6-sabreauto-cs42888",
- "fsl,imx-audio-cs42888";
+ "fsl,imx-audio-cs42888";
model = "imx-cs42888";
- audio-cpu = <&esai>;
- audio-asrc = <&asrc>;
+ esai-controller = <&esai>;
+ asrc-controller = <&asrc>;
audio-codec = <&codec>;
- audio-routing =
- "Line Out Jack", "AOUT1L",
- "Line Out Jack", "AOUT1R",
- "Line Out Jack", "AOUT2L",
- "Line Out Jack", "AOUT2R",
- "Line Out Jack", "AOUT3L",
- "Line Out Jack", "AOUT3R",
- "Line Out Jack", "AOUT4L",
- "Line Out Jack", "AOUT4R",
- "AIN1L", "Line In Jack",
- "AIN1R", "Line In Jack",
- "AIN2L", "Line In Jack",
- "AIN2R", "Line In Jack";
+ };
+
+ sound-hdmi {
+ compatible = "fsl,imx6q-audio-hdmi",
+ "fsl,imx-audio-hdmi";
+ model = "imx-audio-hdmi";
+ hdmi-controller = <&hdmi_audio>;
+ };
+
+ sound-fm {
+ compatible = "fsl,imx-audio-si476x",
+ "fsl,imx-tuner-si476x";
+ model = "imx-radio-si4763";
+ ssi-controller = <&ssi2>;
+ fm-controller = <&si476x_codec>;
+ mux-int-port = <2>;
+ mux-ext-port = <5>;
};
sound-spdif {
@@ -174,19 +276,22 @@
#size-cells = <0>;
reg = <1>;
- adv7180: camera@21 {
- compatible = "adi,adv7180";
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
reg = <0x21>;
- powerdown-gpios = <&max7310_b 2 GPIO_ACTIVE_LOW>;
- interrupt-parent = <&gpio1>;
- interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
-
- port {
- adv7180_to_ipu1_csi0_mux: endpoint {
- remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
- bus-width = <8>;
- };
- };
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_1>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v, enabled via 2.8 VGEN6 */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ pwn-gpios = <&max7310_b 2 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ cvbs = <1>;
};
max7310_a: gpio@30 {
@@ -214,8 +319,9 @@
};
light-sensor@44 {
- compatible = "isil,isl29023";
+ compatible = "fsl,isl29023";
reg = <0x44>;
+ rext = <499>;
interrupt-parent = <&gpio5>;
interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
};
@@ -237,6 +343,25 @@
};
};
};
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
};
&ipu1_csi0_from_ipu1_csi0_mux {
@@ -244,7 +369,10 @@
};
&ipu1_csi0_mux_from_parallel_sensor {
+ /* Downstream driver doesn't use endpoints */
+ /*
remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
+ */
bus-width = <8>;
};
@@ -261,11 +389,23 @@
<&clks IMX6QDL_CLK_PLL4_POST_DIV>;
assigned-clock-parents = <&clks IMX6QDL_CLK_LVDS2_IN>,
<&clks IMX6QDL_PLL4_BYPASS_SRC>,
- <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
- <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>,
+ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>;
assigned-clock-rates = <0>, <0>, <0>, <0>, <24576000>;
};
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-hdmi";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds0";
+ status = "okay";
+};
+
&ecspi1 {
cs-gpios = <&gpio3 19 0>;
pinctrl-names = "default";
@@ -295,15 +435,14 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii-id";
- interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- fsl,err006687-workaround-present;
+ fsl,magic-packet;
status = "okay";
};
&can1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
+ pinctrl-assert-gpios = <&max7310_b 3 GPIO_ACTIVE_HIGH>; /* TX */
xceiver-supply = <&reg_can_stby>;
status = "disabled"; /* pin conflict with fec */
};
@@ -318,13 +457,31 @@
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
+ /* enable at -gpmi-weim.dts due to pin conflict */
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
+&hdmi_audio {
status = "okay";
};
-&hdmi {
+&hdmi_cec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hdmi_cec>;
- ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <1>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ HDMI-supply = <&reg_hdmi>;
status = "okay";
};
@@ -453,6 +610,25 @@
interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
wakeup-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
};
+
+ si4763: si4763@63 {
+ compatible = "si4761";
+ reg = <0x63>;
+ va-supply = <&reg_si4763_va>;
+ vd-supply = <&reg_si4763_vd>;
+ vio1-supply = <&reg_si4763_vio1>;
+ vio2-supply = <&reg_si4763_vio2>;
+ revision-a10; /* set to default A10 compatible command set */
+
+ si476x_codec: si476x-codec {
+ compatible = "si476x-codec";
+ };
+ };
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c3 {
@@ -474,6 +650,14 @@
>;
};
+ pinctrl_audmux: audmux {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0
+ MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ >;
+ };
+
pinctrl_ecspi1: ecspi1grp {
fsl,pins = <
MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
@@ -511,6 +695,12 @@
MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
+
+ pinctrl_enet_irq: enetirqgrp {
+ fsl,pins = <
MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
>;
};
@@ -595,6 +785,30 @@
>;
};
+ pinctrl_ipu1_1: ipu1grp-1 { /* parallel port 16-bit */
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04 0x80000000
+ MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05 0x80000000
+ MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06 0x80000000
+ MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07 0x80000000
+ MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08 0x80000000
+ MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09 0x80000000
+ MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10 0x80000000
+ MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11 0x80000000
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
@@ -636,6 +850,14 @@
>;
};
+ pinctrl_mlb: mlb {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x80000000
+ MX6QDL_PAD_GPIO_6__MLB_SIG 0x80000000
+ MX6QDL_PAD_GPIO_2__MLB_DATA 0x80000000
+ >;
+ };
+
pinctrl_pwm3: pwm1grp {
fsl,pins = <
MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
@@ -660,6 +882,24 @@
>;
};
+ pinctrl_uart3_1: uart3grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3dte_1: uart3dtegrp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CLK__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_CMD__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D30__UART3_RTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_EB3__UART3_CTS_B 0x1b0b1
+ >;
+ };
+
pinctrl_uart4: uart4grp {
fsl,pins = <
MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
@@ -673,6 +913,17 @@
>;
};
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170f9
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100f9
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
@@ -780,6 +1031,7 @@
lvds-channel@0 {
fsl,data-mapping = "spwg";
fsl,data-width = <18>;
+ primary;
status = "okay";
display-timings {
@@ -797,15 +1049,38 @@
};
};
};
+
+ lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing1>;
+ timing1: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ };
+ };
+ };
};
-&pwm3 {
+&mlb {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm3>;
+ pinctrl-0 = <&pinctrl_mlb>;
status = "okay";
};
-&pcie {
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
status = "okay";
};
@@ -815,6 +1090,26 @@
status = "okay";
};
+&ssi2 {
+ assigned-clocks = <&clks IMX6QDL_CLK_SSI2_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>;
+ fsl,mode = "i2s-master";
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3_1>;
+ pinctrl-assert-gpios = <&max7310_b 4 GPIO_ACTIVE_HIGH>, /* CTS */
+ <&max7310_c 3 GPIO_ACTIVE_HIGH>; /* RXD and TXD */
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart3dte_1>; */
+};
+
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4>;
@@ -833,6 +1128,14 @@
status = "okay";
};
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ status = "okay";
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi
new file mode 100644
index 000000000000..cf8604181d32
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is wrote for plugging in Murata 1MW M.2
+ * into SD2 slot by using Murata uSD-to-M.2 Adapter.
+ *
+ * By default, OOB IRQ is enabled with below HW rework.
+ * HW rework:
+ * Install R209,R210,R211,R212,R213,R214,R215 on SDB board.
+ */
+
+/ {
+ leds {
+ compatible = "gpio-leds";
+ status = "disabled";
+ };
+
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&ecspi1 {
+ status = "disabled";
+};
+
+&iomuxc {
+ imx6qdl-sabresd-murata-v2 {
+ pinctrl_btreg: btreggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
+
+ /* add MUXing entry for SD2 4-bit interface and configure control pins */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x13069 /* WL_REG_ON */
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x0b001 /* WL_HOST_WAKE */
+ >;
+ };
+ };
+};
+
+&pinctrl_gpio_leds {
+ fsl,pins = <
+ >;
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5_1
+ &pinctrl_btreg>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
+};
+
+&usdhc2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ pm-ignore-notify;
+ cap-power-off-card;
+ /delete-property/ enable-sdio-wakeup;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&gpio4>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "host-wake";
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index fe59dde41b64..96a4993e84a1 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -8,11 +8,31 @@
#include <dt-bindings/input/input.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
chosen {
stdout-path = &uart1;
};
- memory@10000000 {
+ battery: max8903@0 {
+ compatible = "fsl,max8903-charger";
+ pinctrl-names = "default";
+ dok_input = <&gpio2 24 1>;
+ uok_input = <&gpio1 27 1>;
+ chg_input = <&gpio3 23 1>;
+ flt_input = <&gpio5 2 1>;
+ fsl,dcm_always_high;
+ fsl,dc_valid;
+ fsl,usb_valid;
+ status = "okay";
+ };
+
+ memory: memory@10000000 {
device_type = "memory";
reg = <0x10000000 0x40000000>;
};
@@ -66,6 +86,22 @@
enable-active-high;
};
+ reg_hdmi: regulator-hdmi {
+ compatible = "regulator-fixed";
+ regulator-name = "hdmi-5v-supply";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ hdmi-5v-supply = <&swbst_reg>;
+ };
+
+ reg_mipi_dsi_pwr_on: mipi_dsi_pwr_on {
+ compatible = "regulator-fixed";
+ regulator-name = "mipi_dsi_pwr_on";
+ gpio = <&gpio6 14 0>;
+ enable-active-high;
+ };
+
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -97,17 +133,86 @@
compatible = "fsl,imx6q-sabresd-wm8962",
"fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ audio-cpu = <&ssi2>;
audio-codec = <&codec>;
+ asrc-controller = <&asrc>;
audio-routing =
"Headphone Jack", "HPOUTL",
"Headphone Jack", "HPOUTR",
"Ext Spk", "SPKOUTL",
"Ext Spk", "SPKOUTR",
"AMIC", "MICBIAS",
- "IN3R", "AMIC";
+ "IN3R", "AMIC",
+ "DMIC", "MICBIAS",
+ "DMICDAT", "DMIC",
+ "CPU-Playback", "ASRC-Playback",
+ "Playback", "CPU-Playback",
+ "ASRC-Capture", "CPU-Capture",
+ "CPU-Capture", "Capture";
mux-int-port = <2>;
mux-ext-port = <3>;
+ codec-master;
+ hp-det-gpios = <&gpio7 8 1>;
+ mic-det-gpios = <&gpio1 9 1>;
+ };
+
+ sound-hdmi {
+ compatible = "fsl,imx6q-audio-hdmi",
+ "fsl,imx-audio-hdmi";
+ model = "imx-audio-hdmi";
+ hdmi-controller = <&hdmi_audio>;
+ };
+
+ 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 = <24>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb3: fb@2 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "lcd";
+ interface_pix_fmt = "RGB565";
+ 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 = "ldb";
+ interface_pix_fmt = "RGB666";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1>;
+ status = "okay";
};
backlight_lvds: backlight-lvds {
@@ -123,21 +228,33 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;
- red {
+ charger-led {
gpios = <&gpio1 2 0>;
- default-state = "on";
+ linux,default-trigger = "max8903-charger-charging";
+ retain-state-suspended;
+ default-state = "off";
};
};
- panel {
- compatible = "hannstar,hsd100pxn1";
- backlight = <&backlight_lvds>;
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
- port {
- panel_in: endpoint {
- remote-endpoint = <&lvds0_out>;
- };
- };
+ v4l2_cap_1 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
};
};
@@ -149,7 +266,9 @@
};
&ipu1_csi0_mux_from_parallel_sensor {
+#if 0
remote-endpoint = <&ov5642_to_ipu1_csi0_mux>;
+#endif
};
&ipu1_csi0 {
@@ -160,6 +279,11 @@
&mipi_csi {
status = "okay";
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+#if 0
port@0 {
reg = <0>;
@@ -169,6 +293,17 @@
data-lanes = <1 2>;
};
};
+#endif
+};
+
+&mipi_dsi {
+ dev_id = <0>;
+ disp_id = <1>;
+ lcd_panel = "TRULY-WVGA";
+ disp-power-on-supply = <&reg_mipi_dsi_pwr_on>;
+ reset-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <50>;
+ status = "okay";
};
&audmux {
@@ -180,8 +315,20 @@
&clks {
assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
<&clks IMX6QDL_CLK_LDB_DI1_SEL>;
- assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
- <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL2_PFD0_352M>,
+ <&clks IMX6QDL_CLK_PLL2_PFD0_352M>;
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-hdmi";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds1";
+ status = "okay";
};
&ecspi1 {
@@ -204,20 +351,44 @@
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii-id";
phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ fsl,magic-packet;
status = "okay";
};
-&hdmi {
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hdmi_cec>;
- ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ HDMI-supply = <&reg_hdmi>;
status = "okay";
};
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;
+ sda-gpios = <&gpio5 26 GPIO_ACTIVE_HIGH>;
status = "okay";
codec: wm8962@1a {
@@ -253,6 +424,7 @@
vddio-supply = <&reg_sensors>;
};
+#if 0
ov5642: camera@3c {
compatible = "ovti,ov5642";
pinctrl-names = "default";
@@ -277,12 +449,32 @@
};
};
};
+#endif
+ ov564x: ov564x@3c {
+ compatible = "ovti,ov564x";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_2>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&vgen4_reg>; /* 1.8v */
+ AVDD-supply = <&vgen3_reg>; /* 2.8v, on rev C board is VGEN3, on rev B board is VGEN5 */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio1 16 1>; /* active low: SD1_DAT0 */
+ rst-gpios = <&gpio1 17 0>; /* active high: SD1_DAT1 */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ };
};
&i2c2 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ sda-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
status = "okay";
touchscreen@4 {
@@ -295,6 +487,15 @@
wakeup-gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
};
+ max11801@48 {
+ compatible = "maxim,max11801";
+ reg = <0x48>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 2>;
+ work-mode = <1>;/*DCM mode*/
+ };
+
+#if 0
ov5640: camera@3c {
compatible = "ovti,ov5640";
pinctrl-names = "default";
@@ -317,6 +518,22 @@
};
};
};
+#endif
+
+ ov564x_mipi: ov564x_mipi@3c { /* i2c2 driver */
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&vgen4_reg>; /* 1.8v */
+ AVDD-supply = <&vgen3_reg>; /* 2.8v rev C board is VGEN3 rev B board is VGEN5 */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio1 19 1>; /* active low: SD1_CLK */
+ rst-gpios = <&gpio1 20 0>; /* active high: SD1_DAT2 */
+ csi_id = <1>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ };
pmic: pfuze100@8 {
compatible = "fsl,pfuze100";
@@ -418,12 +635,20 @@
};
};
};
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c3 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+ sda-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
status = "okay";
egalax_ts@4 {
@@ -446,13 +671,14 @@
};
light-sensor@44 {
- compatible = "isil,isl29023";
+ compatible = "fsl,isl29023";
reg = <0x44>;
+ rext = <499>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3_isl29023_int>;
interrupt-parent = <&gpio3>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
- vcc-supply = <&reg_sensors>;
+ vdd-supply = <&reg_sensors>;
};
};
@@ -472,6 +698,13 @@
MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
>;
};
@@ -514,6 +747,12 @@
>;
};
+ pinctrl_enet_irq: enetirqgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
+
pinctrl_gpio_keys: gpio_keysgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
@@ -524,7 +763,14 @@
pinctrl_hdmi_cec: hdmicecgrp {
fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x108b0
+ >;
+ };
+
+ pinctrl_hdmi_hdcp: hdmihdcpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
>;
};
@@ -535,6 +781,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1_gpio_grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x1b8b0
+ >;
+ };
+
pinctrl_i2c1_mma8451_int: i2c1mma8451intgrp {
fsl,pins = <
MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0xb0b1
@@ -548,6 +801,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2_gpio_grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b8b0
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0
+ >;
+ };
+
pinctrl_i2c2_egalax_int: i2c2egalaxintgrp {
fsl,pins = <
MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x1b0b0
@@ -561,6 +821,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3_gpio_grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b8b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ >;
+ };
+
pinctrl_i2c3_isl29023_int: i2c3isl29023intgrp {
fsl,pins = <
MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0xb0b1
@@ -573,6 +840,59 @@
>;
};
+ pinctrl_ipu1: ipu1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000
+ MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000
+ MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x80000000
+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x80000000
+ >;
+ };
+
pinctrl_ipu1_csi0: ipu1csi0grp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
@@ -634,6 +954,24 @@
>;
};
+ pinctrl_uart5_1: uart5grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_COL4__UART5_RTS_B 0x1b0b1
+ MX6QDL_PAD_KEY_ROW4__UART5_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5dte_1: uart5dtegrp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW1__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_COL1__UART5_RX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW4__UART5_RTS_B 0x1b0b1
+ MX6QDL_PAD_KEY_COL4__UART5_CTS_B 0x1b0b1
+ >;
+ };
+
pinctrl_usbotg: usbotggrp {
fsl,pins = <
MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
@@ -704,16 +1042,45 @@
&ldb {
status = "okay";
- lvds-channel@1 {
+ lvds-channel@0 {
fsl,data-mapping = "spwg";
fsl,data-width = <18>;
status = "okay";
- port@4 {
- reg = <4>;
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ };
+ };
+ };
+
+ lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ primary;
+ status = "okay";
- lvds0_out: endpoint {
- remote-endpoint = <&panel_in>;
+ display-timings {
+ native-mode = <&timing1>;
+ timing1: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
};
};
};
@@ -724,7 +1091,7 @@
pinctrl-0 = <&pinctrl_pcie>;
reset-gpio = <&gpio7 12 GPIO_ACTIVE_LOW>;
vpcie-supply = <&reg_pcie>;
- status = "okay";
+ epdev_on-supply = <&vgen3_reg>;
};
&pwm1 {
@@ -757,11 +1124,14 @@
status = "okay";
};
-&snvs_pwrkey {
- status = "okay";
-};
-
&ssi2 {
+ assigned-clocks = <&clks IMX6QDL_CLK_PLL4>,
+ <&clks IMX6QDL_PLL4_BYPASS>,
+ <&clks IMX6QDL_CLK_SSI2_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_OSC>,
+ <&clks IMX6QDL_CLK_PLL4>,
+ <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <737280000>, <0>, <0>;
status = "okay";
};
@@ -808,6 +1178,7 @@
bus-width = <8>;
non-removable;
no-1-8-v;
+ auto-cmd23-broken;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index bc488df31511..a8d043e21b48 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -156,6 +156,11 @@
interrupt-parent = <&gpc>;
ranges;
+ caam_sm: caam-sm@100000 {
+ compatible = "fsl,imx6q-caam-sm";
+ reg = <0x100000 0x4000>;
+ };
+
dma_apbh: dma-apbh@110000 {
compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
reg = <0x00110000 0x2000>;
@@ -215,6 +220,45 @@
};
};
+ hdmi_core: hdmi_core@120000 {
+ compatible = "fsl,imx6q-hdmi-core";
+ reg = <0x120000 0x9000>;
+ clocks = <&clks IMX6QDL_CLK_HDMI_ISFR>,
+ <&clks IMX6QDL_CLK_HDMI_IAHB>,
+ <&clks IMX6QDL_CLK_HSI_TX>;
+ clock-names = "hdmi_isfr", "hdmi_iahb", "mipi_core";
+ status = "disabled";
+ };
+
+ hdmi_video: hdmi_video@20e0000 {
+ compatible = "fsl,imx6q-hdmi-video";
+ reg = <0x20e0000 0x1000>;
+ reg-names = "hdmi_gpr";
+ interrupts = <0 115 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_HDMI_ISFR>,
+ <&clks IMX6QDL_CLK_HDMI_IAHB>,
+ <&clks IMX6QDL_CLK_HSI_TX>;
+ clock-names = "hdmi_isfr", "hdmi_iahb", "mipi_core";
+ status = "disabled";
+ };
+
+ hdmi_audio: hdmi_audio@120000 {
+ compatible = "fsl,imx6q-hdmi-audio";
+ clocks = <&clks IMX6QDL_CLK_HDMI_ISFR>,
+ <&clks IMX6QDL_CLK_HDMI_IAHB>,
+ <&clks IMX6QDL_CLK_HSI_TX>;
+ clock-names = "hdmi_isfr", "hdmi_iahb", "mipi_core";
+ dmas = <&sdma 2 26 0>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
+ hdmi_cec: hdmi_cec@120000 {
+ compatible = "fsl,imx6q-hdmi-cec";
+ interrupts = <0 115 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
gpu_3d: gpu@130000 {
compatible = "vivante,gc";
reg = <0x00130000 0x4000>;
@@ -225,6 +269,7 @@
clock-names = "bus", "core", "shader";
power-domains = <&pd_pu>;
#cooling-cells = <2>;
+ status = "disabled";
};
gpu_2d: gpu@134000 {
@@ -236,6 +281,19 @@
clock-names = "bus", "core";
power-domains = <&pd_pu>;
#cooling-cells = <2>;
+ status = "disabled";
+ };
+
+ ocrams: sram@00900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00900000 0x4000>;
+ clocks = <&clks IMX6QDL_CLK_OCRAM>;
+ };
+
+ ocrams_ddr: sram@00904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00904000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
timer@a00600 {
@@ -318,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_DUMMY>,
+ <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_MLB>,
<&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_SPBA>;
clock-names = "core", "rxtx0",
"rxtx1", "rxtx2",
@@ -337,7 +395,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI1>,
<&clks IMX6QDL_CLK_ECSPI1>;
clock-names = "ipg", "per";
- dmas = <&sdma 3 8 1>, <&sdma 4 8 2>;
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -351,7 +409,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI2>,
<&clks IMX6QDL_CLK_ECSPI2>;
clock-names = "ipg", "per";
- dmas = <&sdma 5 8 1>, <&sdma 6 8 2>;
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -365,7 +423,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI3>,
<&clks IMX6QDL_CLK_ECSPI3>;
clock-names = "ipg", "per";
- dmas = <&sdma 7 8 1>, <&sdma 8 8 2>;
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -379,7 +437,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI4>,
<&clks IMX6QDL_CLK_ECSPI4>;
clock-names = "ipg", "per";
- dmas = <&sdma 9 8 1>, <&sdma 10 8 2>;
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -502,6 +560,24 @@
power-domains = <&pd_pu>;
resets = <&src 1>;
iram = <&ocram>;
+ status = "disabled";
+ };
+
+ vpu_fsl: vpu_fsl@2040000 {
+ compatible = "fsl,imx6-vpu";
+ reg = <0x2040000 0x3c000>;
+ reg-names = "vpu_regs";
+ interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
+ <0 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "vpu_jpu_irq", "vpu_ipi_irq";
+ clocks = <&clks IMX6QDL_CLK_VPU_AXI>,
+ <&clks IMX6QDL_CLK_MMDC_CH0_AXI>,
+ <&clks IMX6QDL_CLK_OCRAM>;
+ clock-names = "vpu_clk", "mmdc_ch0_axi", "ocram";
+ iramsize = <0x21000>;
+ iram = <&ocram>;
+ resets = <&src 1>;
+ power-domains = <&pd_pu>;
};
aipstz@207c000 { /* AIPSTZ1 */
@@ -759,6 +835,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_pu: regulator-vddpu {
@@ -776,6 +853,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_soc: regulator-vddsoc {
@@ -793,6 +871,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
};
@@ -812,6 +891,20 @@
fsl,anatop = <&anatop>;
};
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
+ caam_snvs: caam-snvs@20cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x20cc000 0x4000>;
+ };
+
snvs: snvs@20cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -914,13 +1007,23 @@
};
dcic1: dcic@20e4000 {
- reg = <0x020e4000 0x4000>;
+ compatible = "fsl,imx6q-dcic";
+ reg = <0x20e4000 0x4000>;
interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_DCIC1>, <&clks IMX6QDL_CLK_DCIC1>;
+ clock-names = "dcic", "disp-axi";
+ gpr = <&gpr>;
+ status = "disabled";
};
dcic2: dcic@20e8000 {
- reg = <0x020e8000 0x4000>;
+ compatible = "fsl,imx6q-dcic";
+ reg = <0x20e8000 0x4000>;
interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_DCIC2>, <&clks IMX6QDL_CLK_DCIC2>;
+ clock-names = "dcic", "disp-axi";
+ gpr = <&gpr>;
+ status = "disabled";
};
sdma: sdma@20ec000 {
@@ -1039,20 +1142,28 @@
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupt-names = "int0", "pps";
- interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
- <0 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended =
+ <&gpc 0 118 IRQ_TYPE_LEVEL_HIGH>,
+ <&gpc 0 119 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp";
+ stop-mode = <&gpr 0x34 27>;
+ fsl,wakeup_irq = <0>;
status = "disabled";
};
- mlb@218c000 {
+ mlb: mlb@218c000 {
+ compatible = "fsl,imx6q-mlb150";
reg = <0x0218c000 0x4000>;
interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>,
<0 117 IRQ_TYPE_LEVEL_HIGH>,
<0 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_MLB>;
+ clock-names = "mlb";
+ iram = <&ocram>;
+ status = "disabled";
};
usdhc1: usdhc@2190000 {
@@ -1137,6 +1248,11 @@
reg = <0x021ac000 0x4000>;
};
+ mmdc0-1@021b0000 { /* MMDC0-1 */
+ compatible = "fsl,imx6q-mmdc-combine";
+ reg = <0x021b0000 0x8000>;
+ };
+
mmdc0: memory-controller@21b0000 { /* MMDC0 */
compatible = "fsl,imx6q-mmdc";
reg = <0x021b0000 0x4000>;
@@ -1183,15 +1299,15 @@
};
mipi_csi: mipi@21dc000 {
- compatible = "fsl,imx6-mipi-csi2";
+ compatible = "fsl,imx6q-mipi-csi2";
reg = <0x021dc000 0x4000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <0 100 0x04>, <0 101 0x04>;
clocks = <&clks IMX6QDL_CLK_HSI_TX>,
<&clks IMX6QDL_CLK_VIDEO_27M>,
- <&clks IMX6QDL_CLK_EIM_PODF>;
- clock-names = "dphy", "ref", "pix";
+ <&clks IMX6QDL_CLK_EIM_SEL>;
+ clock-names = "dphy_clk", "cfg_clk", "pixel_clk";
status = "disabled";
};
@@ -1226,6 +1342,7 @@
reg = <0x021e4000 0x4000>;
interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_VDOA>;
+ iram = <&ocram>;
};
uart2: serial@21e8000 {
@@ -1285,10 +1402,15 @@
interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
<0 5 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_IPU1>,
- <&clks IMX6QDL_CLK_IPU1_DI0>,
- <&clks IMX6QDL_CLK_IPU1_DI1>;
- clock-names = "bus", "di0", "di1";
+ <&clks IMX6QDL_CLK_IPU1_DI0>, <&clks IMX6QDL_CLK_IPU1_DI1>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
+ clock-names = "bus",
+ "di0", "di1",
+ "di0_sel", "di1_sel",
+ "ldb_di0", "ldb_di1";
resets = <&src 2>;
+ bypass_reset = <0>;
ipu1_csi0: port@0 {
reg = <0>;
diff --git a/arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts b/arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts
new file mode 100644
index 000000000000..b69e758b36ec
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
+
+
+#include "imx6qp-sabreauto.dts"
+
+&ecspi1 {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&i2c3 {
+ /* pin conflict with ecspi1 */
+ status = "disabled";
+};
+
+&uart3 {
+ /* the uart3 depends on the i2c3, so disable it too. */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ /* max7310_c on i2c3 is gone */
+ status = "okay";
+ dr_mode = "peripheral";
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabreauto-flexcan1.dts b/arch/arm/boot/dts/imx6qp-sabreauto-flexcan1.dts
new file mode 100644
index 000000000000..b57607b0c222
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabreauto-flexcan1.dts
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6qp-sabreauto.dts"
+
+&can1{
+ status = "okay";
+};
+
+&fec {
+ /* pin conflict with flexcan1 */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts b/arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts
new file mode 100644
index 000000000000..1ca09d7dfca5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
+
+#include "imx6qp-sabreauto.dts"
+
+&ecspi1 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&can2 {
+ /* max7310_c on i2c3 is gone */
+ status = "disabled";
+};
+
+&gpmi {
+ compatible = "fsl,imx6qp-gpmi-nand";
+ status = "okay";
+};
+
+&i2c3 {
+ /* pin conflict with weim */
+ status = "disabled";
+};
+
+&uart3 {
+ /* pin conflict with gpmi and weim */
+ status = "disabled";
+};
+
+&usbh1 {
+ /* max7310_b on i2c3 is gone */
+ status = "disabled";
+};
+
+&usbotg {
+ /* max7310_c on i2c3 is gone */
+ status = "okay";
+ dr_mode = "peripheral";
+};
+
+&weim {
+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabreauto.dts b/arch/arm/boot/dts/imx6qp-sabreauto.dts
index d4caeeb0af70..e6a69467a4bb 100644
--- a/arch/arm/boot/dts/imx6qp-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6qp-sabreauto.dts
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+ OR MIT
//
// Copyright 2016 Freescale Semiconductor, Inc.
+// Copyright 2020 NXP
/dts-v1/;
@@ -12,6 +13,62 @@
compatible = "fsl,imx6qp-sabreauto", "fsl,imx6qp";
};
+&pre1 {
+ status = "okay";
+};
+
+&pre2 {
+ status = "okay";
+};
+
+&pre3 {
+ status = "okay";
+};
+
+&pre4 {
+ status = "okay";
+};
+
+&prg1 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&prg2 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&mxcfb1 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb2 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb3 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb4 {
+ prefetch;
+ status = "okay";
+};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
+};
+
&i2c2 {
max7322: gpio@68 {
compatible = "maxim,max7322";
@@ -21,33 +78,13 @@
};
};
-&iomuxc {
- imx6qdl-sabreauto {
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b018
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b018
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b018
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b018
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b018
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b018
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b018
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b018
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b018
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b018
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b018
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b018
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
- };
+&pcie {
+ reset-gpio = <&max7310_c 5 GPIO_ACTIVE_LOW>;
+ status = "okay";
};
-&pcie {
- status = "disabled";
+&sata {
+ status = "okay";
};
&vgen3_reg {
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts
new file mode 100644
index 000000000000..e83d04f14600
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6qp-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts b/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts
new file mode 100644
index 000000000000..e19ff136c226
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6qp-sabresd.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
new file mode 100644
index 000000000000..f33eb65a793e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6qp-sabresd.dts"
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index f1b9cb104fdd..03320e210e24 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -50,6 +50,76 @@
};
};
+&ov564x {
+ AVDD-supply = <&vgen6_reg>; /* 2.8v */
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+};
+
+&ov564x_mipi {
+ AVDD-supply = <&vgen6_reg>; /* 2.8v */
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+};
+
&pcie {
- status = "disabled";
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&pre1 {
+ status = "okay";
+};
+
+&pre2 {
+ status = "okay";
+};
+
+&pre3 {
+ status = "okay";
+};
+
+&pre4 {
+ status = "okay";
+};
+
+&prg1 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&prg2 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&mxcfb1 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb2 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb3 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb4 {
+ prefetch;
+ status = "okay";
+};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
};
diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi
index d91f92f944c5..88bafed79411 100644
--- a/arch/arm/boot/dts/imx6qp.dtsi
+++ b/arch/arm/boot/dts/imx6qp.dtsi
@@ -5,6 +5,15 @@
#include "imx6q.dtsi"
/ {
+ aliases {
+ pre0 = &pre1;
+ pre1 = &pre2;
+ pre2 = &pre3;
+ pre3 = &pre4;
+ prg0 = &prg1;
+ prg1 = &prg2;
+ };
+
soc {
ocram2: sram@940000 {
compatible = "mmio-sram";
@@ -20,57 +29,63 @@
aips-bus@2100000 {
pre1: pre@21c8000 {
- compatible = "fsl,imx6qp-pre";
+ compatible = "fsl,imx6q-pre";
reg = <0x021c8000 0x1000>;
interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
clocks = <&clks IMX6QDL_CLK_PRE0>;
clock-names = "axi";
- fsl,iram = <&ocram2>;
+ ocram = <&ocram2>;
+ status = "disabled";
};
pre2: pre@21c9000 {
- compatible = "fsl,imx6qp-pre";
+ compatible = "fsl,imx6q-pre";
reg = <0x021c9000 0x1000>;
interrupts = <GIC_SPI 97 IRQ_TYPE_EDGE_RISING>;
clocks = <&clks IMX6QDL_CLK_PRE1>;
clock-names = "axi";
- fsl,iram = <&ocram2>;
+ ocram = <&ocram2>;
+ status = "disabled";
};
pre3: pre@21ca000 {
- compatible = "fsl,imx6qp-pre";
+ compatible = "fsl,imx6q-pre";
reg = <0x021ca000 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_EDGE_RISING>;
clocks = <&clks IMX6QDL_CLK_PRE2>;
clock-names = "axi";
- fsl,iram = <&ocram3>;
+ ocram = <&ocram3>;
+ status = "disabled";
};
pre4: pre@21cb000 {
- compatible = "fsl,imx6qp-pre";
+ compatible = "fsl,imx6q-pre";
reg = <0x021cb000 0x1000>;
interrupts = <GIC_SPI 99 IRQ_TYPE_EDGE_RISING>;
clocks = <&clks IMX6QDL_CLK_PRE3>;
clock-names = "axi";
- fsl,iram = <&ocram3>;
+ ocram = <&ocram3>;
+ status = "disabled";
};
prg1: prg@21cc000 {
- compatible = "fsl,imx6qp-prg";
+ compatible = "fsl,imx6q-prg";
reg = <0x021cc000 0x1000>;
clocks = <&clks IMX6QDL_CLK_PRG0_APB>,
<&clks IMX6QDL_CLK_PRG0_AXI>;
- clock-names = "ipg", "axi";
- fsl,pres = <&pre1>, <&pre2>, <&pre3>;
+ clock-names = "apb", "axi";
+ gpr = <&gpr>;
+ status = "disabled";
};
prg2: prg@21cd000 {
- compatible = "fsl,imx6qp-prg";
+ compatible = "fsl,imx6q-prg";
reg = <0x021cd000 0x1000>;
clocks = <&clks IMX6QDL_CLK_PRG1_APB>,
<&clks IMX6QDL_CLK_PRG1_AXI>;
- clock-names = "ipg", "axi";
- fsl,pres = <&pre4>, <&pre2>, <&pre3>;
+ clock-names = "apb", "axi";
+ gpr = <&gpr>;
+ status = "disabled";
};
};
};
@@ -87,22 +102,34 @@
&ipu1 {
compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
+ clocks = <&clks IMX6QDL_CLK_IPU1>,
+ <&clks IMX6QDL_CLK_IPU1_DI0>, <&clks IMX6QDL_CLK_IPU1_DI1>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_SEL>,
+ <&clks IMX6QDL_CLK_PRG0_APB>;
+ clock-names = "bus",
+ "di0", "di1",
+ "di0_sel", "di1_sel",
+ "ldb_di0", "ldb_di1", "prg";
fsl,prg = <&prg1>;
};
&ipu2 {
compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
+ clocks = <&clks IMX6QDL_CLK_IPU2>,
+ <&clks IMX6QDL_CLK_IPU2_DI0>, <&clks IMX6QDL_CLK_IPU2_DI1>,
+ <&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_SEL>,
+ <&clks IMX6QDL_CLK_PRG1_APB>;
+ clock-names = "bus",
+ "di0", "di1",
+ "di0_sel", "di1_sel",
+ "ldb_di0", "ldb_di1", "prg";
fsl,prg = <&prg2>;
};
&ldb {
- clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
- <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
- <&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
- <&clks IMX6QDL_CLK_LDB_DI0_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>;
- clock-names = "di0_pll", "di1_pll",
- "di0_sel", "di1_sel", "di2_sel", "di3_sel",
- "di0", "di1";
+ compatible = "fsl,imx6qp-ldb", "fsl,imx6q-ldb", "fsl,imx53-ldb";
};
&mmdc0 {
diff --git a/arch/arm/boot/dts/imx6sl-evk-btwifi.dts b/arch/arm/boot/dts/imx6sl-evk-btwifi.dts
new file mode 100644
index 000000000000..01867f57d41a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-btwifi.dts
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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.
+ */
+
+/* NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD1
+ * slot using Murata i.MX InterConnect Ver 1.0 Adapter AND wiring in control
+ * signals with SD Card Extender on SD3 slot.
+ * Bluetooth UART connect via SD1 EMMC/MMC Plus pinout.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE are connected from SD Card Extender on SD3
+ * slot.
+ */
+#include "imx6sl-evk.dts"
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio5 16 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&iomuxc {
+ imx6sl-evk-murata-v1_sdext {
+ /* Only MUX SD1_DAT0..3 lines so UART4 can be MUXed on higher data lines. */
+ pinctrl_btreg: btreggrp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_DAT3__GPIO5_IO17 0x13069 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ MX6SL_PAD_SD3_DAT1__GPIO5_IO20 0x13069 /* WL_HOST_WAKE */
+ MX6SL_PAD_SD3_DAT2__GPIO5_IO16 0x13069 /* WL_REG_ON */
+ >;
+ };
+
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ >;
+ };
+ };
+};
+/* Murata: declare UART4 interface for Bluetooth. */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4_1
+ &pinctrl_btreg>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart4dte_1>; */
+};
+
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ pm-ignore-notify;
+ cap-power-off-card;
+ /delete-property/ enable-sdio-wakeup;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ bus-width = <1>;
+ no-1-8-v;
+};
diff --git a/arch/arm/boot/dts/imx6sl-evk-csi.dts b/arch/arm/boot/dts/imx6sl-evk-csi.dts
new file mode 100644
index 000000000000..589d33f715d4
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-csi.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+//Copyright (C) 2013 Freescale Semiconductor, Inc.
+
+#include "imx6sl-evk.dts"
+
+&csi {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&epdc {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sl-evk-ldo.dts b/arch/arm/boot/dts/imx6sl-evk-ldo.dts
new file mode 100644
index 000000000000..5ca3a09df2b9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-ldo.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6sl-evk.dts"
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_pu {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6sl-evk-uart.dts b/arch/arm/boot/dts/imx6sl-evk-uart.dts
new file mode 100644
index 000000000000..6179842731a7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-uart.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6sl-evk.dts"
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4_1>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart4dte_1>; */
+};
+
+&usdhc1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index bc86cfaaa9c2..319c881d631d 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -12,6 +12,19 @@
model = "Freescale i.MX6 SoloLite EVK Board";
compatible = "fsl,imx6sl-evk", "fsl,imx6sl";
+ battery: max8903@0 {
+ compatible = "fsl,max8903-charger";
+ pinctrl-names = "default";
+ dok_input = <&gpio4 13 1>;
+ uok_input = <&gpio4 13 1>;
+ chg_input = <&gpio4 15 1>;
+ flt_input = <&gpio4 14 1>;
+ fsl,dcm_always_high;
+ fsl,dc_valid;
+ fsl,adc_disable;
+ status = "okay";
+ };
+
chosen {
stdout-path = &uart1;
};
@@ -21,6 +34,19 @@
reg = <0x80000000 0x40000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
backlight_display: backlight_display {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
@@ -40,6 +66,11 @@
};
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
compatible = "regulator-fixed";
regulator-name = "usb_otg1_vbus";
@@ -95,7 +126,7 @@
sound {
compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ audio-cpu = <&ssi2>;
audio-codec = <&codec>;
audio-routing =
"Headphone Jack", "HPOUTL",
@@ -106,6 +137,8 @@
"IN3R", "AMIC";
mux-int-port = <2>;
mux-ext-port = <3>;
+ codec-master;
+ hp-det-gpios = <&gpio4 19 1>;
};
panel {
@@ -128,6 +161,14 @@
status = "okay";
};
+&csi {
+ port {
+ csi_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
&ecspi1 {
cs-gpios = <&gpio4 11 0>;
pinctrl-names = "default";
@@ -143,6 +184,15 @@
};
};
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc_0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
&fec {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_fec>;
@@ -151,6 +201,10 @@
status = "okay";
};
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -257,6 +311,89 @@
};
};
};
+
+ elan@10 {
+ compatible = "elan,elan-touch";
+ reg = <0x10>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <10 2>;
+ gpio_elan_cs = <&gpio2 9 0>;
+ gpio_elan_rst = <&gpio4 4 0>;
+ gpio_intr = <&gpio2 10 0>;
+ status = "okay";
+ };
+
+ ma8450@1c {
+ compatible = "fsl,mma8450";
+ reg = <0x1c>;
+ };
+
+ max17135@48 {
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ vneg_pwrup = <1>;
+ gvee_pwrup = <2>;
+ vpos_pwrup = <10>;
+ gvdd_pwrup = <12>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <8>;
+ vneg_pwrdn = <10>;
+ gpio_pmic_pwrgood = <&gpio2 13 0>;
+ gpio_pmic_vcom_ctrl = <&gpio2 3 0>;
+ gpio_pmic_wakeup = <&gpio2 14 0>;
+ gpio_pmic_v3p3 = <&gpio2 7 0>;
+ gpio_pmic_intr = <&gpio2 12 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* Real max value: -500000 */
+ regulator-max-microvolt = <4325000>;
+ /* Real min value: -4325000 */
+ regulator-min-microvolt = <500000>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
+
};
&i2c2 {
@@ -280,6 +417,34 @@
};
};
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "disabled";
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi_0>;
+ clocks = <&clks IMX6SL_CLK_CSI>;
+ clock-names = "csi_mclk";
+ AVDD-supply = <&vgen6_reg>; /* 2.8v */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio1 25 1>;
+ rst-gpios = <&gpio1 26 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi_ep>;
+ };
+ };
+ };
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -295,6 +460,13 @@
MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO2_IO10 0x17000
+ MX6SL_PAD_EPDC_PWRCTRL2__GPIO2_IO09 0x80000000
+ MX6SL_PAD_KEY_COL6__GPIO4_IO04 0x110b0
+ MX6SL_PAD_ECSPI2_MISO__GPIO4_IO14 0x17000
+ MX6SL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x17000
+ MX6SL_PAD_ECSPI2_SS0__GPIO4_IO15 0x17000
+ MX6SL_PAD_FEC_RX_ER__GPIO4_IO19 0x1b0b0
>;
};
@@ -316,6 +488,39 @@
>;
};
+ pinctrl_epdc_0: epdcgrp-0 {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_D0__EPDC_DATA00 0x80000000
+ MX6SL_PAD_EPDC_D1__EPDC_DATA01 0x80000000
+ MX6SL_PAD_EPDC_D2__EPDC_DATA02 0x80000000
+ MX6SL_PAD_EPDC_D3__EPDC_DATA03 0x80000000
+ MX6SL_PAD_EPDC_D4__EPDC_DATA04 0x80000000
+ MX6SL_PAD_EPDC_D5__EPDC_DATA05 0x80000000
+ MX6SL_PAD_EPDC_D6__EPDC_DATA06 0x80000000
+ MX6SL_PAD_EPDC_D7__EPDC_DATA07 0x80000000
+ MX6SL_PAD_EPDC_D8__EPDC_DATA08 0x80000000
+ MX6SL_PAD_EPDC_D9__EPDC_DATA09 0x80000000
+ MX6SL_PAD_EPDC_D10__EPDC_DATA10 0x80000000
+ MX6SL_PAD_EPDC_D11__EPDC_DATA11 0x80000000
+ MX6SL_PAD_EPDC_D12__EPDC_DATA12 0x80000000
+ MX6SL_PAD_EPDC_D13__EPDC_DATA13 0x80000000
+ MX6SL_PAD_EPDC_D14__EPDC_DATA14 0x80000000
+ MX6SL_PAD_EPDC_D15__EPDC_DATA15 0x80000000
+ MX6SL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x80000000
+ MX6SL_PAD_EPDC_GDSP__EPDC_GDSP 0x80000000
+ MX6SL_PAD_EPDC_GDOE__EPDC_GDOE 0x80000000
+ MX6SL_PAD_EPDC_GDRL__EPDC_GDRL 0x80000000
+ MX6SL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x80000000
+ MX6SL_PAD_EPDC_SDOE__EPDC_SDOE 0x80000000
+ MX6SL_PAD_EPDC_SDLE__EPDC_SDLE 0x80000000
+ MX6SL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x80000000
+ MX6SL_PAD_EPDC_BDR0__EPDC_BDR0 0x80000000
+ MX6SL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x80000000
+ MX6SL_PAD_EPDC_SDCE1__EPDC_SDCE1 0x80000000
+ MX6SL_PAD_EPDC_SDCE2__EPDC_SDCE2 0x80000000
+ >;
+ };
+
pinctrl_fec: fecgrp {
fsl,pins = <
MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0
@@ -358,6 +563,13 @@
>;
};
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_SDCE2__I2C3_SCL 0x4001b8b1
+ MX6SL_PAD_EPDC_SDCE3__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
pinctrl_kpp: kppgrp {
fsl,pins = <
MX6SL_PAD_KEY_ROW0__KEY_ROW0 0x1b010
@@ -427,6 +639,24 @@
>;
};
+ pinctrl_uart4_1: uart4grp-1 {
+ fsl,pins = <
+ MX6SL_PAD_SD1_DAT4__UART4_RX_DATA 0x1b0b1
+ MX6SL_PAD_SD1_DAT5__UART4_TX_DATA 0x1b0b1
+ MX6SL_PAD_SD1_DAT7__UART4_CTS_B 0x1b0b1
+ MX6SL_PAD_SD1_DAT6__UART4_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4dte_1: uart4dtegrp-1 {
+ fsl,pins = <
+ MX6SL_PAD_SD1_DAT5__UART4_RX_DATA 0x1b0b1
+ MX6SL_PAD_SD1_DAT4__UART4_TX_DATA 0x1b0b1
+ MX6SL_PAD_SD1_DAT6__UART4_CTS_B 0x1b0b1
+ MX6SL_PAD_SD1_DAT7__UART4_RTS_B 0x1b0b1
+ >;
+ };
+
pinctrl_usbotg1: usbotg1grp {
fsl,pins = <
MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
@@ -543,9 +773,34 @@
MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
>;
};
+
+ pinctrl_csi_0: csigrp-0 {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_GDRL__CSI_MCLK 0x110b0
+ MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x110b0
+ MX6SL_PAD_EPDC_GDSP__CSI_VSYNC 0x110b0
+ MX6SL_PAD_EPDC_GDOE__CSI_HSYNC 0x110b0
+ MX6SL_PAD_EPDC_SDLE__CSI_DATA09 0x110b0
+ MX6SL_PAD_EPDC_SDCLK__CSI_DATA08 0x110b0
+ MX6SL_PAD_EPDC_D7__CSI_DATA07 0x110b0
+ MX6SL_PAD_EPDC_D6__CSI_DATA06 0x110b0
+ MX6SL_PAD_EPDC_D5__CSI_DATA05 0x110b0
+ MX6SL_PAD_EPDC_D4__CSI_DATA04 0x110b0
+ MX6SL_PAD_EPDC_D3__CSI_DATA03 0x110b0
+ MX6SL_PAD_EPDC_D2__CSI_DATA02 0x110b0
+ MX6SL_PAD_EPDC_D1__CSI_DATA01 0x110b0
+ MX6SL_PAD_EPDC_D0__CSI_DATA00 0x110b0
+ MX6SL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000
+ MX6SL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000
+ >;
+ };
};
};
+&pxp {
+ status = "okay";
+};
+
&kpp {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_kpp>;
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 540880f0413f..38233c833ced 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -66,11 +66,17 @@
>;
clock-latency = <61036>; /* two CLK32 periods */
#cooling-cells = <2>;
- clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>,
- <&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_CLK_PLL1_SW>,
- <&clks IMX6SL_CLK_PLL1_SYS>;
+ clocks = <&clks IMX6SL_CLK_ARM>,
+ <&clks IMX6SL_CLK_PLL2_PFD2>,
+ <&clks IMX6SL_CLK_STEP>,
+ <&clks IMX6SL_CLK_PLL1_SW>,
+ <&clks IMX6SL_CLK_PLL1_SYS>,
+ <&clks IMX6SL_CLK_PLL1>,
+ <&clks IMX6SL_PLL1_BYPASS>,
+ <&clks IMX6SL_PLL1_BYPASS_SRC>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1", "pll1_bypass",
+ "pll1_bypass_src";
arm-supply = <&reg_arm>;
pu-supply = <&reg_pu>;
soc-supply = <&reg_soc>;
@@ -118,12 +124,51 @@
interrupt-parent = <&gpc>;
ranges;
- ocram: sram@900000 {
+ busfreq { /* BUSFREQ */
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6SL_CLK_PLL2_BUS>, <&clks IMX6SL_CLK_PLL2_PFD2>,
+ <&clks IMX6SL_CLK_PLL2_198M>, <&clks IMX6SL_CLK_ARM>,
+ <&clks IMX6SL_CLK_PLL3_USB_OTG>, <&clks IMX6SL_CLK_PERIPH>,
+ <&clks IMX6SL_CLK_PRE_PERIPH_SEL>, <&clks IMX6SL_CLK_PERIPH_CLK2_PODF>,
+ <&clks IMX6SL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6SL_CLK_OSC>,
+ <&clks IMX6SL_CLK_PLL1_SYS>, <&clks IMX6SL_CLK_PERIPH2>,
+ <&clks IMX6SL_CLK_AHB>, <&clks IMX6SL_CLK_OCRAM_PODF>,
+ <&clks IMX6SL_CLK_PLL1_SW>, <&clks IMX6SL_CLK_PRE_PERIPH2_SEL>,
+ <&clks IMX6SL_CLK_PERIPH2_CLK2_SEL>, <&clks IMX6SL_CLK_PERIPH2_CLK2_PODF>,
+ <&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_PLL2_BYPASS_SRC>, <&clks IMX6SL_PLL2_BYPASS>,
+ <&clks IMX6SL_CLK_PLL2>, <&clks IMX6SL_CLK_PLL1>, <&clks IMX6SL_PLL1_BYPASS>,
+ <&clks IMX6SL_PLL1_BYPASS_SRC>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "pll1_sys", "periph2", "ahb",
+ "ocram", "pll1_sw", "periph2_pre", "periph2_clk2_sel", "periph2_clk2", "step", "pll2_bypass_src",
+ "pll2_bypass", "pll2", "pll1", "pll1_bypass", "pll1_bypass_src";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ ocrams: sram@900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x900000 0x4000>;
+ clocks = <&clks IMX6SL_CLK_OCRAM>;
+ };
+
+ ocrams_ddr: sram@904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x904000 0x1000>;
+ clocks = <&clks IMX6SL_CLK_OCRAM>;
+ };
+
+ ocram: sram@905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x905000 0x1B000>;
clocks = <&clks IMX6SL_CLK_OCRAM>;
};
+ ocram_optee: sram@918000 {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x918000 0x8000>;
+ overw_reg = <&ocram 0x905000 0x13000>;
+ };
+
intc: interrupt-controller@a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
@@ -591,6 +636,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_pu: regulator-vddpu {
@@ -607,6 +653,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_soc: regulator-vddsoc {
@@ -624,6 +671,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
};
@@ -734,8 +782,14 @@
};
csi: csi@20e4000 {
- reg = <0x020e4000 0x4000>;
+ compatible = "fsl,imx6sl-csi";
+ reg = <0x20e4000 0x4000>;
interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SL_CLK_DUMMY>,
+ <&clks IMX6SL_CLK_DUMMY>,
+ <&clks IMX6SL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
};
spdc: spdc@20e8000 {
@@ -756,13 +810,20 @@
};
pxp: pxp@20f0000 {
- reg = <0x020f0000 0x4000>;
+ compatible = "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
+ reg = <0x20f0000 0x4000>;
interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SL_CLK_PXP_AXI>, <&clks IMX6SL_CLK_DUMMY>;
+ clock-names = "pxp-axi", "disp-axi";
+ status = "disabled";
};
epdc: epdc@20f4000 {
- reg = <0x020f4000 0x4000>;
+ compatible = "fsl,imx6sl-epdc", "fsl,imx6dl-epdc";
+ reg = <0x20f4000 0x4000>;
interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SL_CLK_EPDC_AXI>, <&clks IMX6SL_CLK_EPDC_PIX>;
+ clock-names = "epdc_axi", "epdc_pix";
};
lcdif: lcdif@20f8000 {
diff --git a/arch/arm/boot/dts/imx6sll-evk-btwifi.dts b/arch/arm/boot/dts/imx6sll-evk-btwifi.dts
new file mode 100644
index 000000000000..f025c76cb4c1
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk-btwifi.dts
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is wrote for plugging in Murata 1MW M.2
+ * into SD3 slot by using Murata uSD-to-M.2 Adapter.
+ *
+ * By default, OOB IRQ is not enabled since i.MX6SLL EVK board needs to rework.
+ * How to enable OOB IRQ ?
+ * HW rework:
+ * Install R127 on i.MX6SLL EVK board.
+ * SW change: add below pin for WL_HOST_WAKE
+ * pinctrl_wifi: wifigrp {
+ * fsl,pins = <
+ * ...
+ * MX6SLL_PAD_KEY_COL1__GPIO3_IO26 0x0b001
+ * >;
+ * };
+ * brcmf: bcrmf@1 {
+ * reg = <1>;
+ * compatible = "brcm,bcm4329-fmac";
+ * interrupt-parent = <&gpio3>;
+ * interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ * interrupt-names = "host-wake";
+ * };
+ */
+
+#include "imx6sll-evk.dts"
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio3 27 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&iomuxc {
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130b9
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170b9
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170b9
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170b9
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170b9
+
+ MX6SLL_PAD_KEY_COL0__GPIO3_IO24 0x17059 /* WL_REG_ON */
+ MX6SLL_PAD_KEY_COL1__GPIO3_IO26 0x0b001
+ >;
+ };
+};
+
+&lcdif {
+ status = "disabled";
+};
+
+&reg_sd3_vmmc {
+ regulator-always-on;
+};
+
+&uart5 {
+ resets = <&modem_reset>;
+ status = "okay";
+};
+
+&usdhc3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ pm-ignore-notify;
+ cap-power-off-card;
+ /delete-property/ cd-gpios;
+ /delete-property/ vmmc-supply;
+ /delete-property/ enable-sdio-wakeup;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "host-wake";
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sll-evk-reva.dts b/arch/arm/boot/dts/imx6sll-evk-reva.dts
new file mode 100644
index 000000000000..3704e8543f6f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk-reva.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP.
+ *
+ */
+
+/dts-v1/;
+
+#include "imx6sll-evk.dts"
+
+&usdhc2 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+};
+
diff --git a/arch/arm/boot/dts/imx6sll-evk.dts b/arch/arm/boot/dts/imx6sll-evk.dts
index 5ace9e6acf85..8755d69c499a 100644
--- a/arch/arm/boot/dts/imx6sll-evk.dts
+++ b/arch/arm/boot/dts/imx6sll-evk.dts
@@ -24,6 +24,19 @@
reg = <0x80000000 0x80000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
backlight_display: backlight-display {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
@@ -32,6 +45,19 @@
status = "okay";
};
+ battery: max8903@0 {
+ compatible = "fsl,max8903-charger";
+ pinctrl-names = "default";
+ dok_input = <&gpio4 13 1>;
+ uok_input = <&gpio4 13 1>;
+ chg_input = <&gpio4 15 1>;
+ flt_input = <&gpio4 14 1>;
+ fsl,dcm_always_high;
+ fsl,dc_valid;
+ fsl,adc_disable;
+ status = "okay";
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -44,6 +70,11 @@
};
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
reg_usb_otg1_vbus: regulator-otg1-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -106,9 +137,18 @@
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
+ reg_sd2_vmmc: regulator-sd2-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "eMMC-VCCQ";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
reg_sd3_vmmc: regulator-sd3-vmmc {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -117,28 +157,53 @@
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
- panel {
- compatible = "sii,43wvf1g";
- backlight = <&backlight_display>;
- dvdd-supply = <&reg_lcd_3v3>;
- avdd-supply = <&reg_lcd_5v>;
-
- port {
- panel_in: endpoint {
- remote-endpoint = <&display_out>;
- };
- };
+ sound {
+ compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ audio-cpu = <&ssi2>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
+ mux-int-port = <2>;
+ mux-ext-port = <3>;
+ codec-master;
+ hp-det-gpios = <&gpio4 24 1>;
};
};
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux3>;
+ status = "okay";
+};
+
&cpu0 {
arm-supply = <&sw1a_reg>;
soc-supply = <&sw1c_reg>;
};
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -245,6 +310,98 @@
};
};
};
+
+ max17135: max17135@48 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_max17135>;
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ status = "okay";
+
+ vneg_pwrup = <1>;
+ gvee_pwrup = <2>;
+ vpos_pwrup = <10>;
+ gvdd_pwrup = <12>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <8>;
+ vneg_pwrdn = <10>;
+ gpio_pmic_pwrgood = <&gpio2 13 0>;
+ gpio_pmic_vcom_ctrl = <&gpio2 3 0>;
+ gpio_pmic_wakeup = <&gpio2 14 0>;
+ gpio_pmic_v3p3 = <&gpio2 7 0>;
+ gpio_pmic_intr = <&gpio2 12 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* Real max value: -500000 */
+ regulator-max-microvolt = <4325000>;
+ /* Real min value: -4325000 */
+ regulator-min-microvolt = <500000>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ codec: wm8962@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clks IMX6SLL_CLK_EXTERN_AUDIO>;
+ DCVDD-supply = <&vgen3_reg>;
+ DBVDD-supply = <&reg_aud3v>;
+ AVDD-supply = <&vgen3_reg>;
+ CPVDD-supply = <&vgen3_reg>;
+ MICVDD-supply = <&reg_aud3v>;
+ PLLVDD-supply = <&vgen3_reg>;
+ SPKVDD1-supply = <&reg_aud4v>;
+ SPKVDD2-supply = <&reg_aud4v>;
+ amic-mono;
+ };
};
&lcdif {
@@ -252,9 +409,30 @@
pinctrl-0 = <&pinctrl_lcd>;
status = "okay";
- port {
- display_out: endpoint {
- remote-endpoint = <&panel_in>;
+ lcd-supply = <&reg_lcd_3v3>;
+ display = <&display0>;
+
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
};
};
};
@@ -265,6 +443,10 @@
status = "okay";
};
+&pxp {
+ status = "okay";
+};
+
&snvs_poweroff {
status = "okay";
};
@@ -273,12 +455,26 @@
status = "okay";
};
+&ssi2 {
+ status = "okay";
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
status = "okay";
};
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ fsl,uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart5dte>; */
+ status = "disabled";
+};
+
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -292,6 +488,17 @@
status = "okay";
};
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ vqmmc-supply = <&reg_sd2_vmmc>;
+ status = "okay";
+};
+
&usbotg1 {
vbus-supply = <&reg_usb_otg1_vbus>;
pinctrl-names = "default";
@@ -329,6 +536,69 @@
};
&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* HP DETECT */
+ /* CHG_FLT, CHG_UOK/DOK, CHG_STATUS */
+ MX6SLL_PAD_ECSPI2_MISO__GPIO4_IO14 0x17000
+ MX6SLL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x17000
+ MX6SLL_PAD_ECSPI2_SS0__GPIO4_IO15 0x17000
+ >;
+ };
+
+ pinctrl_audmux3: audmux3grp {
+ fsl,pins = <
+ MX6SLL_PAD_AUD_TXC__AUD3_TXC 0x4130b0
+ MX6SLL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0
+ MX6SLL_PAD_AUD_TXD__AUD3_TXD 0x4110b0
+ MX6SLL_PAD_AUD_RXD__AUD3_RXD 0x4130b0
+ MX6SLL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+ >;
+ };
+
+ pinctrl_epdc0: epdcgrp0 {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_DATA00__EPDC_DATA00 0x100b1
+ MX6SLL_PAD_EPDC_DATA01__EPDC_DATA01 0x100b1
+ MX6SLL_PAD_EPDC_DATA02__EPDC_DATA02 0x100b1
+ MX6SLL_PAD_EPDC_DATA03__EPDC_DATA03 0x100b1
+ MX6SLL_PAD_EPDC_DATA04__EPDC_DATA04 0x100b1
+ MX6SLL_PAD_EPDC_DATA05__EPDC_DATA05 0x100b1
+ MX6SLL_PAD_EPDC_DATA06__EPDC_DATA06 0x100b1
+ MX6SLL_PAD_EPDC_DATA07__EPDC_DATA07 0x100b1
+ MX6SLL_PAD_EPDC_DATA08__EPDC_DATA08 0x100b1
+ MX6SLL_PAD_EPDC_DATA09__EPDC_DATA09 0x100b1
+ MX6SLL_PAD_EPDC_DATA10__EPDC_DATA10 0x100b1
+ MX6SLL_PAD_EPDC_DATA11__EPDC_DATA11 0x100b1
+ MX6SLL_PAD_EPDC_DATA12__EPDC_DATA12 0x100b1
+ MX6SLL_PAD_EPDC_DATA13__EPDC_DATA13 0x100b1
+ MX6SLL_PAD_EPDC_DATA14__EPDC_DATA14 0x100b1
+ MX6SLL_PAD_EPDC_DATA15__EPDC_DATA15 0x100b1
+ MX6SLL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x100b1
+ MX6SLL_PAD_EPDC_SDLE__EPDC_SDLE 0x100b1
+ MX6SLL_PAD_EPDC_SDOE__EPDC_SDOE 0x100b1
+ MX6SLL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x100b1
+ MX6SLL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x100b1
+ MX6SLL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x100b1
+ MX6SLL_PAD_EPDC_GDOE__EPDC_GDOE 0x100b1
+ MX6SLL_PAD_EPDC_GDRL__EPDC_GDRL 0x100b1
+ MX6SLL_PAD_EPDC_GDSP__EPDC_GDSP 0x100b1
+ >;
+ };
+
+ pinctrl_max17135: max17135grp-1 {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_STAT__GPIO2_IO13 0x80000000 /* pwrgood */
+ MX6SLL_PAD_EPDC_VCOM0__GPIO2_IO03 0x80000000 /* vcom_ctrl */
+ MX6SLL_PAD_EPDC_PWR_WAKE__GPIO2_IO14 0x80000000 /* wakeup */
+ MX6SLL_PAD_EPDC_PWR_CTRL0__GPIO2_IO07 0x80000000 /* v3p3 */
+ MX6SLL_PAD_EPDC_PWR_IRQ__GPIO2_IO12 0x80000000 /* pwr int */
+ >;
+ };
+
pinctrl_reg_sd3_vmmc: sd3vmmcgrp {
fsl,pins = <
MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x17059
@@ -366,6 +636,25 @@
>;
};
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SLL_PAD_KEY_ROW1__GPIO3_IO27 0x1b0b1 /* bt reg on */
+ MX6SLL_PAD_ECSPI1_MOSI__UART5_DCE_TX 0x1b0b1
+ MX6SLL_PAD_ECSPI1_SCLK__UART5_DCE_RX 0x1b0b1
+ MX6SLL_PAD_ECSPI1_SS0__UART5_DCE_CTS 0x1b0b1
+ MX6SLL_PAD_ECSPI1_MISO__UART5_DCE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5dte: uart5dtegrp {
+ fsl,pins = <
+ MX6SLL_PAD_ECSPI1_MOSI__UART5_DTE_RX 0x1b0b1
+ MX6SLL_PAD_ECSPI1_SCLK__UART5_DTE_TX 0x1b0b1
+ MX6SLL_PAD_ECSPI1_SS0__UART5_DTE_RTS 0x1b0b1
+ MX6SLL_PAD_ECSPI1_MISO__UART5_DTE_CTS 0x1b0b1
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX6SLL_PAD_SD1_CMD__SD1_CMD 0x17059
@@ -399,6 +688,54 @@
>;
};
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x13059
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x17059
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x17059
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x17059
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x17059
+ MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x17059
+ MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x17059
+ MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x17059
+ MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x17059
+ MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x413059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130b9
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170b9
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170b9
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170b9
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170b9
+ MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x170b9
+ MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x170b9
+ MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x170b9
+ MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x170b9
+ MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x4130b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130f9
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170f9
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170f9
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170f9
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170f9
+ MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x170f9
+ MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x170f9
+ MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x170f9
+ MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x170f9
+ MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x4130f9
+ >;
+ };
+
pinctrl_usbotg1: usbotg1grp {
fsl,pins = <
MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
@@ -448,6 +785,13 @@
>;
};
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SLL_PAD_AUD_RXFS__I2C3_SCL 0x4041b8b1
+ MX6SLL_PAD_AUD_RXC__I2C3_SDA 0x4041b8b1
+ >;
+ };
+
pinctrl_lcd: lcdgrp {
fsl,pins = <
MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x79
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
index 13c7ba7fa6bc..73decc1b5c9e 100644
--- a/arch/arm/boot/dts/imx6sll.dtsi
+++ b/arch/arm/boot/dts/imx6sll.dtsi
@@ -65,13 +65,18 @@
>;
clock-latency = <61036>; /* two CLK32 periods */
#cooling-cells = <2>;
+ fsl,low-power-run;
clocks = <&clks IMX6SLL_CLK_ARM>,
<&clks IMX6SLL_CLK_PLL2_PFD2>,
<&clks IMX6SLL_CLK_STEP>,
<&clks IMX6SLL_CLK_PLL1_SW>,
- <&clks IMX6SLL_CLK_PLL1_SYS>;
+ <&clks IMX6SLL_CLK_PLL1_SYS>,
+ <&clks IMX6SLL_CLK_PLL1>,
+ <&clks IMX6SLL_PLL1_BYPASS>,
+ <&clks IMX6SLL_PLL1_BYPASS_SRC>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1", "pll1_bypass",
+ "pll1_bypass_src";
};
};
@@ -120,9 +125,45 @@
interrupt-parent = <&gpc>;
ranges;
- ocram: sram@900000 {
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6SLL_CLK_PLL2_PFD2>, <&clks IMX6SLL_CLK_PLL2_198M>,
+ <&clks IMX6SLL_CLK_PLL2_BUS>, <&clks IMX6SLL_CLK_ARM>,
+ <&clks IMX6SLL_CLK_PLL3_USB_OTG>, <&clks IMX6SLL_CLK_PERIPH>,
+ <&clks IMX6SLL_CLK_PERIPH_PRE>, <&clks IMX6SLL_CLK_PERIPH_CLK2>,
+ <&clks IMX6SLL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6SLL_CLK_OSC>,
+ <&clks IMX6SLL_CLK_AHB>, <&clks IMX6SLL_CLK_AXI_PODF>,
+ <&clks IMX6SLL_CLK_PERIPH2>, <&clks IMX6SLL_CLK_PERIPH2_PRE>,
+ <&clks IMX6SLL_CLK_PERIPH2_CLK2>, <&clks IMX6SLL_CLK_PERIPH2_CLK2_SEL>,
+ <&clks IMX6SLL_CLK_STEP>, <&clks IMX6SLL_CLK_MMDC_P0_FAST>, <&clks IMX6SLL_PLL1_BYPASS_SRC>,
+ <&clks IMX6SLL_PLL1_BYPASS>, <&clks IMX6SLL_CLK_PLL1_SYS>, <&clks IMX6SLL_CLK_PLL1_SW>,
+ <&clks IMX6SLL_CLK_PLL1>;
+ clock-names = "pll2_pfd2_396m", "pll2_198m", "pll2_bus", "arm", "pll3_usb_otg",
+ "periph", "periph_pre", "periph_clk2", "periph_clk2_sel", "osc",
+ "ahb", "ocram", "periph2", "periph2_pre", "periph2_clk2", "periph2_clk2_sel",
+ "step", "mmdc", "pll1_bypass_src", "pll1_bypass", "pll1_sys", "pll1_sw", "pll1";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ ocrams: sram@900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x900000 0x4000>;
+ };
+
+ ocrams_ddr: sram@904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x904000 0x1000>;
+ };
+
+ ocram: sram@905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x905000 0x1B000>;
+ };
+
+ ocram_optee: sram@918000 {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x918000 0x8000>;
+ overw_reg = <&ocram 0x905000 0x13000>;
};
intc: interrupt-controller@a01000 {
@@ -183,7 +224,7 @@
};
ecspi1: spi@2008000 {
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible ="fsl,imx51-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
@@ -195,7 +236,7 @@
};
ecspi2: spi@200c000 {
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx51-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
@@ -207,7 +248,7 @@
};
ecspi3: spi@2010000 {
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx51-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
@@ -219,7 +260,7 @@
};
ecspi4: spi@2014000 {
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx51-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
@@ -596,6 +637,7 @@
#interrupt-cells = <3>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x7c00000 0x7d00 0x0 0x1400640>;
};
iomuxc: pinctrl@20e0000 {
@@ -621,7 +663,7 @@
};
sdma: dma-controller@20ec000 {
- compatible = "fsl,imx6sll-sdma", "fsl,imx6ul-sdma";
+ compatible = "fsl,imx6ul-sdma", "fsl,imx35-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_IPG>,
@@ -632,6 +674,26 @@
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
};
+ pxp: pxp@20f0000 {
+ compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
+ reg = <0x20f0000 0x4000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_PXP>;
+ clock-names = "pxp_ipg", "pxp_axi";
+ status = "disabled";
+ };
+
+ epdc: epdc@20f4000 {
+ compatible = "fsl,imx6sll-epdc", "fsl,imx7d-epdc";
+ reg = <0x20f4000 0x4000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_EPDC_AXI>, <&clks IMX6SLL_CLK_EPDC_PIX>;
+ clock-names = "epdc_axi", "epdc_pix";
+ status = "disabled";
+ };
+
lcdif: lcd-controller@20f8000 {
compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
reg = <0x020f8000 0x4000>;
@@ -698,7 +760,7 @@
};
usdhc1: mmc@2190000 {
- compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_USDHC1>,
@@ -712,7 +774,7 @@
};
usdhc2: mmc@2194000 {
- compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_USDHC2>,
@@ -726,7 +788,7 @@
};
usdhc3: mmc@2198000 {
- compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_USDHC3>,
@@ -775,6 +837,13 @@
clocks = <&clks IMX6SLL_CLK_MMDC_P0_IPG>;
};
+ rngb: rng@21b4000 {
+ compatible = "fsl,imx25-rngb";
+ reg = <0x021b4000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>;
+ };
+
ocotp: ocotp-ctrl@21bc000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h
index aa194a2fdd53..df9a6c5b5ada 100644
--- a/arch/arm/boot/dts/imx6sx-pinfunc.h
+++ b/arch/arm/boot/dts/imx6sx-pinfunc.h
@@ -66,6 +66,7 @@
#define MX6SX_PAD_GPIO1_IO06__ENET2_MDC 0x002C 0x0374 0x0000 0x2 0x0
#define MX6SX_PAD_GPIO1_IO06__CSI1_MCLK 0x002C 0x0374 0x0000 0x3 0x0
#define MX6SX_PAD_GPIO1_IO06__UART1_RTS_B 0x002C 0x0374 0x082C 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART1_CTS_B 0x002C 0x0374 0x0000 0x4 0x0
#define MX6SX_PAD_GPIO1_IO06__GPIO1_IO_6 0x002C 0x0374 0x0000 0x5 0x0
#define MX6SX_PAD_GPIO1_IO06__SRC_ANY_PU_RESET 0x002C 0x0374 0x0000 0x6 0x0
#define MX6SX_PAD_GPIO1_IO06__OCOTP_CTRL_WRAPPER_FUSE_LATCHED 0x002C 0x0374 0x0000 0x7 0x0
@@ -75,6 +76,7 @@
#define MX6SX_PAD_GPIO1_IO07__ENET2_MDIO 0x0030 0x0378 0x0770 0x2 0x0
#define MX6SX_PAD_GPIO1_IO07__AUDMUX_MCLK 0x0030 0x0378 0x0000 0x3 0x0
#define MX6SX_PAD_GPIO1_IO07__UART1_CTS_B 0x0030 0x0378 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO07__UART1_RTS_B 0x0030 0x0378 0x082C 0x4 0x1
#define MX6SX_PAD_GPIO1_IO07__GPIO1_IO_7 0x0030 0x0378 0x0000 0x5 0x0
#define MX6SX_PAD_GPIO1_IO07__SRC_EARLY_RESET 0x0030 0x0378 0x0000 0x6 0x0
#define MX6SX_PAD_GPIO1_IO07__DCIC2_OUT 0x0030 0x0378 0x0000 0x7 0x0
@@ -84,6 +86,7 @@
#define MX6SX_PAD_GPIO1_IO08__SDMA_EXT_EVENT_0 0x0034 0x037C 0x081C 0x2 0x0
#define MX6SX_PAD_GPIO1_IO08__CCM_PMIC_RDY 0x0034 0x037C 0x069C 0x3 0x1
#define MX6SX_PAD_GPIO1_IO08__UART2_RTS_B 0x0034 0x037C 0x0834 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO08__UART2_CTS_B 0x0034 0x037C 0x0000 0x4 0x0
#define MX6SX_PAD_GPIO1_IO08__GPIO1_IO_8 0x0034 0x037C 0x0000 0x5 0x0
#define MX6SX_PAD_GPIO1_IO08__SRC_SYSTEM_RESET 0x0034 0x037C 0x0000 0x6 0x0
#define MX6SX_PAD_GPIO1_IO08__DCIC1_OUT 0x0034 0x037C 0x0000 0x7 0x0
@@ -93,6 +96,7 @@
#define MX6SX_PAD_GPIO1_IO09__SDMA_EXT_EVENT_1 0x0038 0x0380 0x0820 0x2 0x0
#define MX6SX_PAD_GPIO1_IO09__CCM_OUT0 0x0038 0x0380 0x0000 0x3 0x0
#define MX6SX_PAD_GPIO1_IO09__UART2_CTS_B 0x0038 0x0380 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO09__UART2_RTS_B 0x0038 0x0380 0x0834 0x4 0x1
#define MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x0038 0x0380 0x0000 0x5 0x0
#define MX6SX_PAD_GPIO1_IO09__SRC_INT_BOOT 0x0038 0x0380 0x0000 0x6 0x0
#define MX6SX_PAD_GPIO1_IO09__OBSERVE_MUX_OUT_4 0x0038 0x0380 0x0000 0x7 0x0
@@ -200,6 +204,7 @@
#define MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x0064 0x03AC 0x07C0 0x2 0x2
#define MX6SX_PAD_CSI_DATA06__KPP_COL_7 0x0064 0x03AC 0x07D0 0x3 0x0
#define MX6SX_PAD_CSI_DATA06__UART6_RTS_B 0x0064 0x03AC 0x0854 0x4 0x0
+#define MX6SX_PAD_CSI_DATA06__UART6_CTS_B 0x0064 0x03AC 0x0000 0x4 0x0
#define MX6SX_PAD_CSI_DATA06__GPIO1_IO_20 0x0064 0x03AC 0x0000 0x5 0x0
#define MX6SX_PAD_CSI_DATA06__WEIM_DATA_17 0x0064 0x03AC 0x0000 0x6 0x0
#define MX6SX_PAD_CSI_DATA06__DCIC2_OUT 0x0064 0x03AC 0x0000 0x7 0x0
@@ -210,6 +215,7 @@
#define MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x0068 0x03B0 0x07C4 0x2 0x2
#define MX6SX_PAD_CSI_DATA07__KPP_ROW_7 0x0068 0x03B0 0x07DC 0x3 0x0
#define MX6SX_PAD_CSI_DATA07__UART6_CTS_B 0x0068 0x03B0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA07__UART6_RTS_B 0x0068 0x03B0 0x0854 0x4 0x1
#define MX6SX_PAD_CSI_DATA07__GPIO1_IO_21 0x0068 0x03B0 0x0000 0x5 0x0
#define MX6SX_PAD_CSI_DATA07__WEIM_DATA_16 0x0068 0x03B0 0x0000 0x6 0x0
#define MX6SX_PAD_CSI_DATA07__DCIC1_OUT 0x0068 0x03B0 0x0000 0x7 0x0
@@ -219,6 +225,7 @@
#define MX6SX_PAD_CSI_HSYNC__ESAI_TX0 0x006C 0x03B4 0x0790 0x1 0x1
#define MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x006C 0x03B4 0x0678 0x2 0x1
#define MX6SX_PAD_CSI_HSYNC__UART4_RTS_B 0x006C 0x03B4 0x0844 0x3 0x2
+#define MX6SX_PAD_CSI_HSYNC__UART4_CTS_B 0x006C 0x03B4 0x0000 0x3 0x0
#define MX6SX_PAD_CSI_HSYNC__MQS_LEFT 0x006C 0x03B4 0x0000 0x4 0x0
#define MX6SX_PAD_CSI_HSYNC__GPIO1_IO_22 0x006C 0x03B4 0x0000 0x5 0x0
#define MX6SX_PAD_CSI_HSYNC__WEIM_DATA_25 0x006C 0x03B4 0x0000 0x6 0x0
@@ -251,6 +258,7 @@
#define MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0 0x0078 0x03C0 0x07A4 0x1 0x1
#define MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x0078 0x03C0 0x0674 0x2 0x1
#define MX6SX_PAD_CSI_VSYNC__UART4_CTS_B 0x0078 0x03C0 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_VSYNC__UART4_RTS_B 0x0078 0x03C0 0x0844 0x3 0x3
#define MX6SX_PAD_CSI_VSYNC__MQS_RIGHT 0x0078 0x03C0 0x0000 0x4 0x0
#define MX6SX_PAD_CSI_VSYNC__GPIO1_IO_25 0x0078 0x03C0 0x0000 0x5 0x0
#define MX6SX_PAD_CSI_VSYNC__WEIM_DATA_24 0x0078 0x03C0 0x0000 0x6 0x0
@@ -353,6 +361,7 @@
#define MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x009C 0x03E4 0x0000 0x1 0x0
#define MX6SX_PAD_ENET2_RX_CLK__I2C3_SCL 0x009C 0x03E4 0x07B8 0x2 0x1
#define MX6SX_PAD_ENET2_RX_CLK__UART1_RTS_B 0x009C 0x03E4 0x082C 0x3 0x2
+#define MX6SX_PAD_ENET2_RX_CLK__UART1_CTS_B 0x009C 0x03E4 0x0000 0x3 0x0
#define MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x009C 0x03E4 0x07EC 0x4 0x1
#define MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8 0x009C 0x03E4 0x0000 0x5 0x0
#define MX6SX_PAD_ENET2_RX_CLK__USB_OTG2_OC 0x009C 0x03E4 0x085C 0x6 0x1
@@ -363,6 +372,7 @@
#define MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x00A0 0x03E8 0x076C 0x1 0x1
#define MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x00A0 0x03E8 0x07BC 0x2 0x1
#define MX6SX_PAD_ENET2_TX_CLK__UART1_CTS_B 0x00A0 0x03E8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__UART1_RTS_B 0x00A0 0x03E8 0x082C 0x3 0x3
#define MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x00A0 0x03E8 0x07E8 0x4 0x1
#define MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 0x00A0 0x03E8 0x0000 0x5 0x0
#define MX6SX_PAD_ENET2_TX_CLK__USB_OTG2_PWR 0x00A0 0x03E8 0x0000 0x6 0x0
@@ -372,6 +382,7 @@
#define MX6SX_PAD_KEY_COL0__KPP_COL_0 0x00A4 0x03EC 0x0000 0x0 0x0
#define MX6SX_PAD_KEY_COL0__USDHC3_CD_B 0x00A4 0x03EC 0x0000 0x1 0x0
#define MX6SX_PAD_KEY_COL0__UART6_RTS_B 0x00A4 0x03EC 0x0854 0x2 0x2
+#define MX6SX_PAD_KEY_COL0__UART6_CTS_B 0x00A4 0x03EC 0x0000 0x2 0x0
#define MX6SX_PAD_KEY_COL0__ECSPI1_SCLK 0x00A4 0x03EC 0x0710 0x3 0x0
#define MX6SX_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x00A4 0x03EC 0x066C 0x4 0x0
#define MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x00A4 0x03EC 0x0000 0x5 0x0
@@ -390,6 +401,7 @@
#define MX6SX_PAD_KEY_COL2__KPP_COL_2 0x00AC 0x03F4 0x0000 0x0 0x0
#define MX6SX_PAD_KEY_COL2__USDHC4_CD_B 0x00AC 0x03F4 0x0874 0x1 0x1
#define MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x00AC 0x03F4 0x084C 0x2 0x2
+#define MX6SX_PAD_KEY_COL2__UART5_CTS_B 0x00AC 0x03F4 0x0000 0x2 0x0
#define MX6SX_PAD_KEY_COL2__CAN1_TX 0x00AC 0x03F4 0x0000 0x3 0x0
#define MX6SX_PAD_KEY_COL2__CANFD_TX1 0x00AC 0x03F4 0x0000 0x4 0x0
#define MX6SX_PAD_KEY_COL2__GPIO2_IO_12 0x00AC 0x03F4 0x0000 0x5 0x0
@@ -415,6 +427,7 @@
#define MX6SX_PAD_KEY_ROW0__KPP_ROW_0 0x00B8 0x0400 0x0000 0x0 0x0
#define MX6SX_PAD_KEY_ROW0__USDHC3_WP 0x00B8 0x0400 0x0000 0x1 0x0
#define MX6SX_PAD_KEY_ROW0__UART6_CTS_B 0x00B8 0x0400 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW0__UART6_RTS_B 0x00B8 0x0400 0x0854 0x2 0x3
#define MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI 0x00B8 0x0400 0x0718 0x3 0x0
#define MX6SX_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x00B8 0x0400 0x0660 0x4 0x0
#define MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x00B8 0x0400 0x0000 0x5 0x0
@@ -434,6 +447,7 @@
#define MX6SX_PAD_KEY_ROW2__KPP_ROW_2 0x00C0 0x0408 0x0000 0x0 0x0
#define MX6SX_PAD_KEY_ROW2__USDHC4_WP 0x00C0 0x0408 0x0878 0x1 0x1
#define MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x00C0 0x0408 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW2__UART5_RTS_B 0x00C0 0x0408 0x084C 0x2 0x3
#define MX6SX_PAD_KEY_ROW2__CAN1_RX 0x00C0 0x0408 0x068C 0x3 0x1
#define MX6SX_PAD_KEY_ROW2__CANFD_RX1 0x00C0 0x0408 0x0694 0x4 0x1
#define MX6SX_PAD_KEY_ROW2__GPIO2_IO_17 0x00C0 0x0408 0x0000 0x5 0x0
@@ -816,6 +830,7 @@
#define MX6SX_PAD_NAND_DATA04__USDHC2_DATA4 0x0160 0x04A8 0x0000 0x1 0x0
#define MX6SX_PAD_NAND_DATA04__QSPI2_B_SS1_B 0x0160 0x04A8 0x0000 0x2 0x0
#define MX6SX_PAD_NAND_DATA04__UART3_RTS_B 0x0160 0x04A8 0x083C 0x3 0x0
+#define MX6SX_PAD_NAND_DATA04__UART3_CTS_B 0x0160 0x04A8 0x0000 0x3 0x0
#define MX6SX_PAD_NAND_DATA04__AUDMUX_AUD4_RXFS 0x0160 0x04A8 0x0650 0x4 0x0
#define MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x0160 0x04A8 0x0000 0x5 0x0
#define MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0x0160 0x04A8 0x0000 0x6 0x0
@@ -826,6 +841,7 @@
#define MX6SX_PAD_NAND_DATA05__USDHC2_DATA5 0x0164 0x04AC 0x0000 0x1 0x0
#define MX6SX_PAD_NAND_DATA05__QSPI2_B_DQS 0x0164 0x04AC 0x0000 0x2 0x0
#define MX6SX_PAD_NAND_DATA05__UART3_CTS_B 0x0164 0x04AC 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA05__UART3_RTS_B 0x0164 0x04AC 0x083C 0x3 0x1
#define MX6SX_PAD_NAND_DATA05__AUDMUX_AUD4_RXC 0x0164 0x04AC 0x064C 0x4 0x0
#define MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0x0164 0x04AC 0x0000 0x5 0x0
#define MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0x0164 0x04AC 0x0000 0x6 0x0
@@ -968,6 +984,7 @@
#define MX6SX_PAD_QSPI1A_SS1_B__SDMA_DEBUG_PC_3 0x019C 0x04E4 0x0000 0x9 0x0
#define MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0 0x01A0 0x04E8 0x0000 0x0 0x0
#define MX6SX_PAD_QSPI1B_DATA0__UART3_CTS_B 0x01A0 0x04E8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__UART3_RTS_B 0x01A0 0x04E8 0x083C 0x1 0x4
#define MX6SX_PAD_QSPI1B_DATA0__ECSPI3_MOSI 0x01A0 0x04E8 0x0738 0x2 0x1
#define MX6SX_PAD_QSPI1B_DATA0__ESAI_RX_FS 0x01A0 0x04E8 0x0778 0x3 0x2
#define MX6SX_PAD_QSPI1B_DATA0__CSI1_DATA_22 0x01A0 0x04E8 0x06F4 0x4 0x1
@@ -976,6 +993,7 @@
#define MX6SX_PAD_QSPI1B_DATA0__SIM_M_HADDR_9 0x01A0 0x04E8 0x0000 0x7 0x0
#define MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1 0x01A4 0x04EC 0x0000 0x0 0x0
#define MX6SX_PAD_QSPI1B_DATA1__UART3_RTS_B 0x01A4 0x04EC 0x083C 0x1 0x5
+#define MX6SX_PAD_QSPI1B_DATA1__UART3_CTS_B 0x01A4 0x04EC 0x0000 0x1 0x0
#define MX6SX_PAD_QSPI1B_DATA1__ECSPI3_MISO 0x01A4 0x04EC 0x0734 0x2 0x1
#define MX6SX_PAD_QSPI1B_DATA1__ESAI_RX_CLK 0x01A4 0x04EC 0x0788 0x3 0x2
#define MX6SX_PAD_QSPI1B_DATA1__CSI1_DATA_21 0x01A4 0x04EC 0x06F0 0x4 0x1
@@ -1247,6 +1265,7 @@
#define MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x0230 0x0578 0x0000 0x2 0x0
#define MX6SX_PAD_SD1_DATA2__GPT_COMPARE2 0x0230 0x0578 0x0000 0x3 0x0
#define MX6SX_PAD_SD1_DATA2__UART2_CTS_B 0x0230 0x0578 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA2__UART2_RTS_B 0x0230 0x0578 0x0834 0x4 0x2
#define MX6SX_PAD_SD1_DATA2__GPIO6_IO_4 0x0230 0x0578 0x0000 0x5 0x0
#define MX6SX_PAD_SD1_DATA2__ECSPI4_RDY 0x0230 0x0578 0x0000 0x6 0x0
#define MX6SX_PAD_SD1_DATA2__CCM_OUT0 0x0230 0x0578 0x0000 0x7 0x0
@@ -1256,6 +1275,7 @@
#define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD 0x0234 0x057C 0x065C 0x2 0x2
#define MX6SX_PAD_SD1_DATA3__GPT_COMPARE3 0x0234 0x057C 0x0000 0x3 0x0
#define MX6SX_PAD_SD1_DATA3__UART2_RTS_B 0x0234 0x057C 0x0834 0x4 0x3
+#define MX6SX_PAD_SD1_DATA3__UART2_CTS_B 0x0234 0x057C 0x0000 0x4 0x0
#define MX6SX_PAD_SD1_DATA3__GPIO6_IO_5 0x0234 0x057C 0x0000 0x5 0x0
#define MX6SX_PAD_SD1_DATA3__ECSPI4_SS1 0x0234 0x057C 0x0000 0x6 0x0
#define MX6SX_PAD_SD1_DATA3__CCM_PMIC_RDY 0x0234 0x057C 0x069C 0x7 0x2
@@ -1326,6 +1346,7 @@
#define MX6SX_PAD_SD2_DATA3__MMDC_DEBUG_31 0x024C 0x0594 0x0000 0x9 0x0
#define MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x0250 0x0598 0x0000 0x0 0x0
#define MX6SX_PAD_SD3_CLK__UART4_CTS_B 0x0250 0x0598 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_CLK__UART4_RTS_B 0x0250 0x0598 0x0844 0x1 0x0
#define MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x0250 0x0598 0x0740 0x2 0x0
#define MX6SX_PAD_SD3_CLK__AUDMUX_AUD6_RXFS 0x0250 0x0598 0x0680 0x3 0x0
#define MX6SX_PAD_SD3_CLK__LCDIF2_VSYNC 0x0250 0x0598 0x0000 0x4 0x0
@@ -1365,6 +1386,7 @@
#define MX6SX_PAD_SD3_DATA1__SDMA_DEBUG_EVT_CHN_LINES_1 0x025C 0x05A4 0x0000 0x9 0x0
#define MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x0260 0x05A8 0x0000 0x0 0x0
#define MX6SX_PAD_SD3_DATA2__UART4_RTS_B 0x0260 0x05A8 0x0844 0x1 0x1
+#define MX6SX_PAD_SD3_DATA2__UART4_CTS_B 0x0260 0x05A8 0x0000 0x1 0x0
#define MX6SX_PAD_SD3_DATA2__ECSPI4_SS0 0x0260 0x05A8 0x074C 0x2 0x0
#define MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS 0x0260 0x05A8 0x0688 0x3 0x0
#define MX6SX_PAD_SD3_DATA2__LCDIF2_CLK 0x0260 0x05A8 0x0000 0x4 0x0
@@ -1410,6 +1432,7 @@
#define MX6SX_PAD_SD3_DATA6__CAN2_TX 0x0270 0x05B8 0x0000 0x1 0x0
#define MX6SX_PAD_SD3_DATA6__CANFD_TX2 0x0270 0x05B8 0x0000 0x2 0x0
#define MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x0270 0x05B8 0x083C 0x3 0x2
+#define MX6SX_PAD_SD3_DATA6__UART3_CTS_B 0x0270 0x05B8 0x0000 0x3 0x0
#define MX6SX_PAD_SD3_DATA6__LCDIF2_DATA_4 0x0270 0x05B8 0x0000 0x4 0x0
#define MX6SX_PAD_SD3_DATA6__GPIO7_IO_8 0x0270 0x05B8 0x0000 0x5 0x0
#define MX6SX_PAD_SD3_DATA6__ENET1_1588_EVENT0_OUT 0x0270 0x05B8 0x0000 0x6 0x0
@@ -1420,6 +1443,7 @@
#define MX6SX_PAD_SD3_DATA7__CAN1_RX 0x0274 0x05BC 0x068C 0x1 0x0
#define MX6SX_PAD_SD3_DATA7__CANFD_RX1 0x0274 0x05BC 0x0694 0x2 0x0
#define MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x0274 0x05BC 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA7__UART3_RTS_B 0x0274 0x05BC 0x083C 0x3 0x3
#define MX6SX_PAD_SD3_DATA7__LCDIF2_DATA_5 0x0274 0x05BC 0x0000 0x4 0x0
#define MX6SX_PAD_SD3_DATA7__GPIO7_IO_9 0x0274 0x05BC 0x0000 0x5 0x0
#define MX6SX_PAD_SD3_DATA7__ENET1_1588_EVENT0_IN 0x0274 0x05BC 0x0000 0x6 0x0
@@ -1511,6 +1535,7 @@
#define MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x0298 0x05E0 0x0000 0x0 0x0
#define MX6SX_PAD_SD4_DATA6__RAWNAND_CE3_B 0x0298 0x05E0 0x0000 0x1 0x0
#define MX6SX_PAD_SD4_DATA6__UART5_RTS_B 0x0298 0x05E0 0x084C 0x2 0x0
+#define MX6SX_PAD_SD4_DATA6__UART5_CTS_B 0x0298 0x05E0 0x0000 0x2 0x0
#define MX6SX_PAD_SD4_DATA6__ECSPI3_MISO 0x0298 0x05E0 0x0734 0x3 0x0
#define MX6SX_PAD_SD4_DATA6__LCDIF2_DATA_6 0x0298 0x05E0 0x0000 0x4 0x0
#define MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x0298 0x05E0 0x0000 0x5 0x0
@@ -1521,6 +1546,7 @@
#define MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x029C 0x05E4 0x0000 0x0 0x0
#define MX6SX_PAD_SD4_DATA7__RAWNAND_DATA08 0x029C 0x05E4 0x0000 0x1 0x0
#define MX6SX_PAD_SD4_DATA7__UART5_CTS_B 0x029C 0x05E4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA7__UART5_RTS_B 0x029C 0x05E4 0x084C 0x2 0x1
#define MX6SX_PAD_SD4_DATA7__ECSPI3_SS0 0x029C 0x05E4 0x073C 0x3 0x0
#define MX6SX_PAD_SD4_DATA7__LCDIF2_DATA_15 0x029C 0x05E4 0x0000 0x4 0x0
#define MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x029C 0x05E4 0x0000 0x5 0x0
diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts
index e4719566133c..8131116c2186 100644
--- a/arch/arm/boot/dts/imx6sx-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts
@@ -66,12 +66,153 @@
enable-active-high;
vin-supply = <&reg_can_en>;
};
+
+ reg_vref_3v3: regulator-adc-verf {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_audio: cs42888_supply {
+ compatible = "regulator-fixed";
+ regulator-name = "cs42888_supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ si4763_vio1: vio1_tnr {
+ compatible = "regulator-fixed";
+ regulator-name = "vio1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ si4763_vio2: vio2_tnr {
+ compatible = "regulator-fixed";
+ regulator-name = "vio2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ si4763_vd: f3v3_tnr {
+ compatible = "regulator-fixed";
+ regulator-name = "vd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ si4763_va: f5v_tnr {
+ compatible = "regulator-fixed";
+ regulator-name = "va";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ sound-cs42888 {
+ compatible = "fsl,imx6-sabreauto-cs42888",
+ "fsl,imx-audio-cs42888";
+ model = "imx-cs42888";
+ esai-controller = <&esai>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&codec>;
+ };
+
+ sound-fm {
+ compatible = "fsl,imx-audio-si476x",
+ "fsl,imx-tuner-si476x";
+ model = "imx-radio-si4763";
+
+ ssi-controller = <&ssi2>;
+ fm-controller = <&si476x_codec>;
+ mux-int-port = <2>;
+ mux-ext-port = <5>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-in;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
+
+&adc2 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
};
&anaclk2 {
clock-frequency = <24576000>;
};
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux_3>;
+ status = "okay";
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6SX_PLL4_BYPASS_SRC>,
+ <&clks IMX6SX_PLL4_BYPASS>,
+ <&clks IMX6SX_CLK_PLL4_POST_DIV>;
+ assigned-clock-parents = <&clks IMX6SX_CLK_LVDS2_IN>,
+ <&clks IMX6SX_PLL4_BYPASS_SRC>;
+ assigned-clock-rates = <0>, <0>, <24576000>;
+};
+
+&esai {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esai_2>;
+ assigned-clocks = <&clks IMX6SX_CLK_ESAI_SEL>,
+ <&clks IMX6SX_CLK_ESAI_EXTAL>;
+ assigned-clock-parents = <&clks IMX6SX_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <24576000>;
+ status = "okay";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif_3>;
+ status = "okay";
+};
+
+&ssi2 {
+ fsl,mode = "i2s-master";
+ status = "okay";
+};
+
+&csi2 {
+ status = "okay";
+ port {
+ csi2_ep: endpoint {
+ remote-endpoint = <&vadc_ep>;
+ };
+ };
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-lcdif1";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds";
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
@@ -87,11 +228,13 @@
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
+ at803x,eee-disabled;
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
+ at803x,eee-disabled;
};
};
};
@@ -119,12 +262,62 @@
status = "okay";
};
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
+&qspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi1_1>;
+ status = "okay";
+ ddrsmp=<2>;
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ reg = <0>;
+ };
+
+ flash1: n25q256a@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ reg = <2>;
+ };
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
status = "okay";
};
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode;*/
+ /* pinctrl-0 = <&pinctrl_uart5dte>; */
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
@@ -151,6 +344,14 @@
};
&iomuxc {
+ pinctrl_audmux_3: audmux-3 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_CMD__AUDMUX_AUD5_RXC 0x130b0
+ MX6SX_PAD_SD1_CLK__AUDMUX_AUD5_RXFS 0x130b0
+ MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD 0x130b0
+ >;
+ };
+
pinctrl_egalax_int: egalax-intgrp {
fsl,pins = <
MX6SX_PAD_SD4_RESET_B__GPIO6_IO_22 0x10b0
@@ -193,6 +394,27 @@
>;
};
+ pinctrl_esai_2: esaigrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__ESAI_TX_CLK 0x1b030
+ MX6SX_PAD_CSI_DATA01__ESAI_TX_FS 0x1b030
+ MX6SX_PAD_CSI_HSYNC__ESAI_TX0 0x1b030
+ MX6SX_PAD_CSI_DATA04__ESAI_TX1 0x1b030
+ MX6SX_PAD_CSI_DATA06__ESAI_TX2_RX3 0x1b030
+ MX6SX_PAD_CSI_DATA07__ESAI_TX3_RX2 0x1b030
+ MX6SX_PAD_CSI_DATA02__ESAI_RX_CLK 0x1b030
+ MX6SX_PAD_CSI_DATA03__ESAI_RX_FS 0x1b030
+ MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0 0x1b030
+ MX6SX_PAD_CSI_DATA05__ESAI_TX4_RX1 0x1b030
+ >;
+ };
+
+ pinctrl_spdif_3: spdifgrp-3 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
+ >;
+ };
+
pinctrl_flexcan1: flexcan1grp {
fsl,pins = <
MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
@@ -207,6 +429,27 @@
>;
};
+ pinctrl_gpmi_nand_1: gpmi-nand-1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1
+ MX6SX_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1
+ MX6SX_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1
+ MX6SX_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000
+ MX6SX_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1
+ MX6SX_PAD_NAND_CE1_B__RAWNAND_CE1_B 0xb0b1
+ MX6SX_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1
+ MX6SX_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1
+ MX6SX_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1
+ MX6SX_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1
+ MX6SX_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1
+ MX6SX_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1
+ MX6SX_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1
+ MX6SX_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1
+ MX6SX_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1
+ MX6SX_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
@@ -227,6 +470,23 @@
>;
};
+ pinctrl_qspi1_1: qspi1grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA0__QSPI1_A_DATA_0 0x70a1
+ MX6SX_PAD_QSPI1A_DATA1__QSPI1_A_DATA_1 0x70a1
+ MX6SX_PAD_QSPI1A_DATA2__QSPI1_A_DATA_2 0x70a1
+ MX6SX_PAD_QSPI1A_DATA3__QSPI1_A_DATA_3 0x70a1
+ MX6SX_PAD_QSPI1A_SCLK__QSPI1_A_SCLK 0x70a1
+ MX6SX_PAD_QSPI1A_SS0_B__QSPI1_A_SS0_B 0x70a1
+ MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0 0x70a1
+ MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1 0x70a1
+ MX6SX_PAD_QSPI1B_DATA2__QSPI1_B_DATA_2 0x70a1
+ MX6SX_PAD_QSPI1B_DATA3__QSPI1_B_DATA_3 0x70a1
+ MX6SX_PAD_QSPI1B_SCLK__QSPI1_B_SCLK 0x70a1
+ MX6SX_PAD_QSPI1B_SS0_B__QSPI1_B_SS0_B 0x70a1
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
@@ -234,6 +494,31 @@
>;
};
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5dte: uart5dtegrp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_TX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_RX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_RTS_B 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_CTS_B 0x1b0b1
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
@@ -313,6 +598,31 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ codec: cs42888@48 {
+ compatible = "cirrus,cs42888";
+ reg = <0x48>;
+ clocks = <&anaclk2 0>;
+ clock-names = "mclk";
+ VA-supply = <&reg_audio>;
+ VD-supply = <&reg_audio>;
+ VLS-supply = <&reg_audio>;
+ VLC-supply = <&reg_audio>;
+ };
+
+ si4763: si4763@63 {
+ compatible = "si4761";
+ reg = <0x63>;
+ va-supply = <&si4763_va>;
+ vd-supply = <&si4763_vd>;
+ vio1-supply = <&si4763_vio1>;
+ vio2-supply = <&si4763_vio2>;
+ revision-a10; /* set to default A10 compatible command set */
+
+ si476x_codec: si476x-codec {
+ compatible = "si476x-codec";
+ };
+ };
+
touchscreen@4 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
@@ -452,6 +762,42 @@
gpio-controller;
#gpio-cells = <2>;
};
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <7>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <24 8>;
+ interrupt-route = <1>;
+ };
+
+ mag3110@e {
+ compatible = "fsl,mag3110";
+ reg = <0xe>;
+ position = <2>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <6 1>;
+ };
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <23 2>;
+ };
+};
+
+&vadc {
+ vadc_in = <0>;
+ csi_id = <1>;
+ status = "okay";
+ port {
+ vadc_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
};
&wdog1 {
diff --git a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
new file mode 100644
index 000000000000..ab4cde5fe76b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is wrote for plugging in Murata 1MW M.2
+ * into SD2 slot by using Murata uSD-to-M.2 Adapter.
+ *
+ * By default, OOB IRQ is not enabled since i.MX6SX SDB board needs to rework.
+ * How to enable OOB IRQ ?
+ * HW rework:
+ * Install R328 on i.MX6SX SDB board.
+ * SW change:
+ * pinctrl_wifi: wifigrp {
+ * fsl,pins = <
+ * MX6SX_PAD_ENET1_RX_CLK__GPIO2_IO_4 0x0b001
+ * >;
+ * };
+ * brcmf: bcrmf@1 {
+ * reg = <1>;
+ * compatible = "brcm,bcm4329-fmac";
+ * interrupt-parent = <&gpio2>;
+ * interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ * interrupt-names = "host-wake";
+ * };
+ */
+
+#include "imx6sx-sdb.dts"
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ usdhc2_pwrseq: usdhc2_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ };
+};
+
+&iomuxc {
+ imx6sx-sdb-murata-wifibt {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_DATA06__GPIO4_IO_10 0x13069 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ >;
+ };
+ };
+};
+
+&uart5 { /* for bluetooth */
+ pinctrl-0 = <&pinctrl_uart5 &pinctrl_bt>;
+ resets = <&modem_reset>;
+};
+
+
+&usdhc2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2 &pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v; /* force 3.3V VIO */
+ non-removable;
+ mmc-pwrseq = <&usdhc2_pwrseq>;
+ pm-ignore-notify;
+ cap-power-off-card;
+ /delete-property/ wakeup-source;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-emmc.dts b/arch/arm/boot/dts/imx6sx-sdb-emmc.dts
new file mode 100644
index 000000000000..b829d7dbe368
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-emmc.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6sx-sdb.dts"
+
+/*
+ * The eMMC chip on imx6sx sdb board is DNP by default.
+ * Need do hw rework to burn the eMMC4.5 chip on the eMMC socket on uSDHC4
+ * and connect eMMC signals as well as disconnect BOOT SD CARD slot signals
+ */
+&usdhc4 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc4_1>;
+ pinctrl-1 = <&pinctrl_usdhc4_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc4_1_200mhz>;
+ bus-width = <8>;
+ auto-cmd23-broken;
+ /*
+ * overwrite cd-gpios and wp-gpios since they are reused as eMMC DATA
+ * signals after rework
+ */
+ cd-gpios = <>;
+ wp-gpios = <>;
+ non-removable;
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts b/arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts
new file mode 100644
index 000000000000..23f69ef9b1e6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ */
+
+#include "imx6sx-sdb.dts"
+
+/ {
+ sii902x_reset: sii902x-reset {
+ status = "okay";
+ };
+};
+
+&csi1 {
+ status = "disabled";
+};
+
+&lcdif1 {
+ status = "okay";
+};
+
+&i2c1 {
+ sii902x@39 {
+ status = "okay";
+ };
+};
+
+&ov5640 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-ldo.dts b/arch/arm/boot/dts/imx6sx-sdb-ldo.dts
new file mode 100644
index 000000000000..3a8c194ba2d6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-ldo.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6sx-sdb.dts"
+
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1075000
+ 198000 975000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1175000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <0>;
+};
+
+&gpc {
+ fsl,ldo-bypass = <0>; /* use ldo-enable, u-boot will check it and configure */
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-m4.dts b/arch/arm/boot/dts/imx6sx-sdb-m4.dts
new file mode 100644
index 000000000000..80db8b9dbef6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-m4.dts
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6sx-sdb.dts"
+
+/{
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ m4_reserved: m4@0x9ff00000 {
+ no-map;
+ reg = <0x9ff00000 0x100000>;
+ };
+
+ rpmsg_reserved: rpmsg@0xbff00000 {
+ no-map;
+ reg = <0xbff00000 0x100000>;
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+};
+
+/*
+ * The flollowing modules are conflicting with M4, disable them when m4
+ * is running.
+ */
+&adc1 {
+ status = "disabled";
+};
+
+&adc2 {
+ status = "disabled";
+};
+
+&flexcan1 {
+ status = "disabled";
+};
+
+&flexcan2 {
+ status = "disabled";
+};
+
+&i2c3 {
+ status = "disabled";
+};
+
+&ocram {
+ reg = <0x00901000 0xf000>;
+};
+
+&qspi2 {
+ status = "disabled";
+};
+
+&qspi_m4 {
+ status = "okay";
+};
+
+&rpmsg{
+ vdev-nums = <1>;
+ reg = <0xbfff0000 0x10000>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&clks {
+ fsl,shared-clks-number = <0x23>;
+ fsl,shared-clks-index = <IMX6SX_CLK_PLL2_BUS IMX6SX_CLK_PLL2_PFD0
+ IMX6SX_CLK_PLL2_PFD2 IMX6SX_CLK_PLL3_USB_OTG
+ IMX6SX_CLK_PLL3_PFD1 IMX6SX_CLK_PLL3_PFD2
+ IMX6SX_CLK_PLL3_PFD3 IMX6SX_CLK_PLL4_AUDIO
+ IMX6SX_CLK_PLL5_VIDEO
+ IMX6SX_CLK_OCRAM IMX6SX_CLK_CAN1_SERIAL
+ IMX6SX_CLK_CAN1_IPG IMX6SX_CLK_CAN2_SERIAL
+ IMX6SX_CLK_CAN2_IPG IMX6SX_CLK_CANFD
+ IMX6SX_CLK_ECSPI1 IMX6SX_CLK_ECSPI2
+ IMX6SX_CLK_ECSPI3 IMX6SX_CLK_ECSPI4
+ IMX6SX_CLK_ECSPI5 IMX6SX_CLK_QSPI1
+ IMX6SX_CLK_QSPI2 IMX6SX_CLK_SSI1
+ IMX6SX_CLK_SSI2 IMX6SX_CLK_SSI3
+ IMX6SX_CLK_UART_SERIAL IMX6SX_CLK_UART_IPG
+ IMX6SX_CLK_PERIPH_CLK2_SEL IMX6SX_CLK_DUMMY
+ IMX6SX_CLK_I2C1 IMX6SX_CLK_I2C2
+ IMX6SX_CLK_I2C3 IMX6SX_CLK_I2C4
+ IMX6SX_CLK_EPIT1 IMX6SX_CLK_EPIT2>;
+ fsl,shared-mem-addr = <0x91F000>;
+ fsl,shared-mem-size = <0x1000>;
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-mqs.dts b/arch/arm/boot/dts/imx6sx-sdb-mqs.dts
new file mode 100644
index 000000000000..3aae33f7f144
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-mqs.dts
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
+
+#include "imx6sx-sdb.dts"
+/ {
+
+ sound {
+ status = "disabled";
+ };
+
+ sound-mqs {
+ compatible = "fsl,imx6sx-sdb-mqs",
+ "fsl,imx-audio-mqs";
+ model = "mqs-audio";
+ cpu-dai = <&sai1>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&mqs>;
+ };
+};
+
+&usdhc2 {
+ /* pin conflict with mqs*/
+ status = "disabled";
+};
+
+&mqs {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mqs>;
+ clocks = <&clks IMX6SX_CLK_SAI1>;
+ clock-names = "mclk";
+ status = "okay";
+};
+
+&sai1 {
+ pinctrl-0 = <>;
+ status = "okay";
+};
+
+&ssi2 {
+ status = "disabled";
+};
+
+&sdma {
+ gpr = <&gpr>;
+ /* SDMA event remap for SAI1 */
+ fsl,sdma-event-remap = <0 15 1>, <0 16 1>;
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-reva-ldo.dts b/arch/arm/boot/dts/imx6sx-sdb-reva-ldo.dts
new file mode 100644
index 000000000000..867199915236
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-reva-ldo.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6sx-sdb-reva.dts"
+
+&gpc {
+ fsl,ldo-bypass = <0>; /* use ldo-enable, u-boot will check it and configure */
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index 5a63ca615722..6a1dba0fb699 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -103,6 +103,23 @@
};
};
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ >;
+
+ fsl,arm-soc-shared = <1>;
+};
+
&qspi2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi2>;
@@ -131,10 +148,12 @@
&reg_arm {
vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
};
&reg_soc {
vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
};
&reg_vdd1p1 {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi
index 865528b134d8..fbae20d2a2c0 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi
@@ -28,6 +28,14 @@
default-brightness-level = <6>;
};
+ backlight2 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm4 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ fb-names = "mxs-lcdif1";
+ };
+
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -56,6 +64,7 @@
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
@@ -93,6 +102,7 @@
regulator-name = "lcd-3v3";
gpio = <&gpio3 27 0>;
enable-active-high;
+ status = "disabled";
};
reg_peri_3v3: regulator-peri-3v3 {
@@ -151,10 +161,22 @@
regulator-max-microvolt = <3300000>;
};
+ reg_vref_3v3: regulator-adc-verf {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
sound {
compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ audio-cpu = <&ssi2>;
audio-codec = <&codec>;
audio-routing =
"Headphone Jack", "HPOUTL",
@@ -165,28 +187,78 @@
"IN3R", "AMIC";
mux-int-port = <2>;
mux-ext-port = <6>;
+ codec-master;
+ hp-det-gpios = <&gpio1 17 1>;
};
- panel {
- compatible = "sii,43wvf1g";
- backlight = <&backlight_display>;
- dvdd-supply = <&reg_lcd_3v3>;
- avdd-supply = <&reg_lcd_5v>;
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sx-sdb-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
- port {
- panel_in: endpoint {
- remote-endpoint = <&display_out>;
- };
- };
+ sii902x_reset: sii902x-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio3 27 1>;
+ reset-delay-us = <100000>;
+ #reset-cells = <0>;
+ status = "disabled";
};
};
+&adc1 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
+
+&adc2 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
+
&audmux {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
status = "okay";
};
+&csi1 {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&csi2 {
+ status = "okay";
+ port {
+ csi2_ep: endpoint {
+ remote-endpoint = <&vadc_ep>;
+ };
+ };
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-lcdif1";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds";
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
@@ -202,10 +274,12 @@
ethphy1: ethernet-phy@1 {
reg = <1>;
+ at803x,eee-disabled;
};
ethphy2: ethernet-phy@2 {
reg = <2>;
+ at803x,eee-disabled;
};
};
};
@@ -232,11 +306,99 @@
status = "okay";
};
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi_0>;
+ clocks = <&clks IMX6SX_CLK_CSI>;
+ clock-names = "csi_mclk";
+ AVDD-supply = <&vgen3_reg>; /* 2.8v */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio3 28 1>;
+ rst-gpios = <&gpio3 27 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+
+ sii902x@39 {
+ compatible = "SiI,sii902x";
+ interrupt-parent = <&gpio4>;
+ interrupts = <21 2>;
+ mode_str ="1280x720M@60";
+ bits-per-pixel = <16>;
+ resets = <&sii902x_reset>;
+ reg = <0x39>;
+ status = "disabled";
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ egalax_ts@4 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_egalax_int>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <19 2>;
+ wakeup-gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+
&i2c3 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <5 1>;
+ shared-interrupt;
+ };
+
+ mag3110@e {
+ compatible = "fsl,mag3110";
+ reg = <0xe>;
+ position = <2>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <5 1>;
+ shared-interrupt;
+ };
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <1>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <2 8>;
+ interrupt-route = <2>;
+ };
};
&i2c4 {
@@ -271,11 +433,65 @@
&lcdif1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcd>;
+ lcd-supply = <&reg_lcd_3v3>;
+ display = <&display0>;
+ status = "disabled";
+
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&lcdif2 {
+ display = <&display1>;
+ disp-dev = "ldb";
status = "okay";
+ display1: display@1 {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+ };
+};
- port {
- display_out: endpoint {
- remote-endpoint = <&panel_in>;
+&ldb {
+ status = "okay";
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ crtc = "lcdif2";
+ status = "okay";
+ display-timings {
+ native-mode = <&timing1>;
+ timing1: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ };
};
};
};
@@ -286,6 +502,16 @@
status = "okay";
};
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
&snvs_poweroff {
status = "okay";
};
@@ -296,7 +522,20 @@
status = "disabled";
};
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ status = "okay";
+};
+
&ssi2 {
+ assigned-clocks = <&clks IMX6SX_CLK_PLL4>,
+ <&clks IMX6SX_PLL4_BYPASS>,
+ <&clks IMX6SX_CLK_SSI2_SEL>;
+ assigned-clock-parents = <&clks IMX6SX_CLK_OSC>,
+ <&clks IMX6SX_CLK_PLL4>,
+ <&clks IMX6SX_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <737280000>, <0>, <0>;
status = "okay";
};
@@ -311,6 +550,9 @@
pinctrl-0 = <&pinctrl_uart5>;
uart-has-rtscts;
status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode;*/
+ /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
};
&usbotg1 {
@@ -374,6 +616,24 @@
&iomuxc {
imx6x-sdb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_can_gpios>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA0__GPIO6_IO_2 0x17059
+ MX6SX_PAD_SD1_DATA3__GPIO6_IO_5 0xb000
+ MX6SX_PAD_CSI_DATA03__GPIO1_IO_17 0x17059
+ >;
+ };
+
+ pinctrl_can_gpios: can-gpios {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25 0x17059
+ MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x17059
+ >;
+ };
+
pinctrl_audmux: audmuxgrp {
fsl,pins = <
MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
@@ -384,11 +644,38 @@
>;
};
+ pinctrl_csi_0: csigrp-0 {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA07__CSI1_MCLK 0x110b0
+ MX6SX_PAD_LCD1_DATA06__CSI1_PIXCLK 0x110b0
+ MX6SX_PAD_LCD1_DATA04__CSI1_VSYNC 0x110b0
+ MX6SX_PAD_LCD1_DATA05__CSI1_HSYNC 0x110b0
+ MX6SX_PAD_LCD1_DATA17__CSI1_DATA_0 0x110b0
+ MX6SX_PAD_LCD1_DATA16__CSI1_DATA_1 0x110b0
+ MX6SX_PAD_LCD1_DATA15__CSI1_DATA_2 0x110b0
+ MX6SX_PAD_LCD1_DATA14__CSI1_DATA_3 0x110b0
+ MX6SX_PAD_LCD1_DATA13__CSI1_DATA_4 0x110b0
+ MX6SX_PAD_LCD1_DATA12__CSI1_DATA_5 0x110b0
+ MX6SX_PAD_LCD1_DATA11__CSI1_DATA_6 0x110b0
+ MX6SX_PAD_LCD1_DATA10__CSI1_DATA_7 0x110b0
+ MX6SX_PAD_LCD1_DATA09__CSI1_DATA_8 0x110b0
+ MX6SX_PAD_LCD1_DATA08__CSI1_DATA_9 0x110b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x80000000
+ MX6SX_PAD_LCD1_VSYNC__GPIO3_IO_28 0x80000000
+ >;
+ };
+
+ pinctrl_egalax_int: egalax_intgrp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA3__GPIO4_IO_19 0x80000000
+ >;
+ };
+
pinctrl_enet1: enet1grp {
fsl,pins = <
MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
- MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b1
+ MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b9
MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
@@ -457,6 +744,13 @@
>;
};
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
@@ -529,6 +823,12 @@
>;
};
+ pinctrl_pwm4: pwm4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x110b0
+ >;
+ };
+
pinctrl_qspi2: qspi2grp {
fsl,pins = <
MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1
@@ -552,6 +852,13 @@
>;
};
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x120b0
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x120b0
+ >;
+ };
+
pinctrl_sai1: sai1grp {
fsl,pins = <
MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0
@@ -562,6 +869,12 @@
>;
};
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
@@ -578,6 +891,15 @@
>;
};
+ pinctrl_uart5dte_1: uart5dtegrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_TX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_RX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_RTS_B 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_CTS_B 0x1b0b1
+ >;
+ };
+
pinctrl_usb_otg1: usbotg1grp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
@@ -667,6 +989,51 @@
>;
};
+ pinctrl_usdhc4_1: usdhc4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
+ MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x17059
+ MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x17059
+ MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x17059
+ MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc4_1_100mhz: usdhc4grp-1-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170b9
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100b9
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x170b9
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x170b9
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x170b9
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x170b9
+ MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x170b9
+ MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x170b9
+ MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x170b9
+ MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc4_1_200mhz: usdhc4grp-1-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170f9
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100f9
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x170f9
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x170f9
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x170f9
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x170f9
+ MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x170f9
+ MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x170f9
+ MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x170f9
+ MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x170f9
+ >;
+ };
+
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
@@ -674,3 +1041,14 @@
};
};
};
+
+&vadc {
+ vadc_in = <0>;
+ csi_id = <1>;
+ status = "okay";
+ port {
+ vadc_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 531a52c1e987..26912390f882 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -82,14 +82,32 @@
<&clks IMX6SX_CLK_PLL2_PFD2>,
<&clks IMX6SX_CLK_STEP>,
<&clks IMX6SX_CLK_PLL1_SW>,
- <&clks IMX6SX_CLK_PLL1_SYS>;
+ <&clks IMX6SX_CLK_PLL1_SYS>,
+ <&clks IMX6SX_CLK_PLL1>,
+ <&clks IMX6SX_PLL1_BYPASS>,
+ <&clks IMX6SX_PLL1_BYPASS_SRC>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1",
+ "pll1_bypass", "pll1_bypass_src";
arm-supply = <&reg_arm>;
soc-supply = <&reg_soc>;
};
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
ckil: clock-ckil {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -160,18 +178,61 @@
interrupt-parent = <&gpc>;
ranges;
- ocram_s: sram@8f8000 {
- compatible = "mmio-sram";
- reg = <0x008f8000 0x4000>;
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6SX_CLK_PLL2_BUS>, <&clks IMX6SX_CLK_PLL2_PFD2>,
+ <&clks IMX6SX_CLK_PLL2_198M>, <&clks IMX6SX_CLK_ARM>,
+ <&clks IMX6SX_CLK_PLL3_USB_OTG>, <&clks IMX6SX_CLK_PERIPH>,
+ <&clks IMX6SX_CLK_PERIPH_PRE>, <&clks IMX6SX_CLK_PERIPH_CLK2>,
+ <&clks IMX6SX_CLK_PERIPH_CLK2_SEL>, <&clks IMX6SX_CLK_OSC>,
+ <&clks IMX6SX_CLK_PLL1_SYS>, <&clks IMX6SX_CLK_PERIPH2>,
+ <&clks IMX6SX_CLK_AHB>, <&clks IMX6SX_CLK_OCRAM_PODF>,
+ <&clks IMX6SX_CLK_PLL1_SW>, <&clks IMX6SX_CLK_PERIPH2_PRE>,
+ <&clks IMX6SX_CLK_PERIPH2_CLK2_SEL>, <&clks IMX6SX_CLK_PERIPH2_CLK2>,
+ <&clks IMX6SX_CLK_STEP>, <&clks IMX6SX_CLK_MMDC_PODF>,
+ <&clks IMX6SX_CLK_M4>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm",
+ "pll3_usb_otg", "periph", "periph_pre", "periph_clk2",
+ "periph_clk2_sel", "osc", "pll1_sys", "periph2",
+ "ahb", "ocram", "pll1_sw", "periph2_pre",
+ "periph2_clk2_sel", "periph2_clk2", "step", "mmdc",
+ "m4";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ ocrams: sram@8f8000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x8f8000 0x4000>;
clocks = <&clks IMX6SX_CLK_OCRAM_S>;
};
- ocram: sram@900000 {
+ ocrams_ddr: sram@900000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x900000 0x1000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM>;
+ };
+
+ ocram: sram@901000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x901000 0x1F000>;
clocks = <&clks IMX6SX_CLK_OCRAM>;
};
+ ocram_mf: sram-mf@900000 {
+ compatible = "fsl,mega-fast-sram";
+ reg = <0x900000 0x20000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM>;
+ };
+
+ ocram_optee {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x8f8000 0x4000>;
+ overw_reg = <&ocrams_ddr 0x904000 0x1000>,
+ <&ocram 0x905000 0x1b000>,
+ <&ocrams 0x900000 0x4000>;
+ overw_clock = <&ocrams &clks IMX6SX_CLK_OCRAM>;
+ };
+
intc: interrupt-controller@a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
@@ -200,6 +261,23 @@
<&clks IMX6SX_CLK_GPU>;
clock-names = "bus", "core", "shader";
power-domains = <&pd_pu>;
+ status = "disabled";
+ };
+
+ gpu3d: gpu3d@1800000 {
+ compatible = "fsl,imx6sx-gpu", "fsl,imx6q-gpu";
+ reg = <0x1800000 0x4000>, <0x80000000 0x0>,
+ <0x0 0x8000000>;
+ reg-names = "iobase_3d", "phys_baseaddr", "contiguous_mem";
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_3d";
+ clocks = <&clks IMX6SX_CLK_GPU_AXI_PODF>, <&clks IMX6SX_CLK_GPU>,
+ <&clks 0>;
+ clock-names = "gpu3d_axi_clk", "gpu3d_clk",
+ "gpu3d_shader_clk";
+ resets = <&src 0>;
+ reset-names = "gpu3d";
+ power-domains = <&pd_pu>;
};
dma_apbh: dma-apbh@1804000 {
@@ -215,6 +293,11 @@
clocks = <&clks IMX6SX_CLK_APBH_DMA>;
};
+ caam_sm: caam-sm@100000 {
+ compatible = "fsl,imx6q-caam-sm";
+ reg = <0x100000 0x8000>;
+ };
+
gpmi: gpmi-nand@1806000{
compatible = "fsl,imx6sx-gpmi-nand";
#address-cells = <1>;
@@ -333,6 +416,7 @@
};
esai: esai@2024000 {
+ compatible = "fsl,imx35-esai";
reg = <0x02024000 0x4000>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ESAI_IPG>,
@@ -342,6 +426,9 @@
<&clks IMX6SX_CLK_SPBA>;
clock-names = "core", "mem", "extal",
"fsys", "spba";
+ dmas = <&sdma 23 21 0>,
+ <&sdma 24 21 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -388,18 +475,27 @@
};
asrc: asrc@2034000 {
+ compatible = "fsl,imx53-asrc";
reg = <0x02034000 0x4000>;
- interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SX_CLK_ASRC_MEM>,
- <&clks IMX6SX_CLK_ASRC_IPG>,
- <&clks IMX6SX_CLK_SPDIF>,
- <&clks IMX6SX_CLK_SPBA>;
- clock-names = "mem", "ipg", "asrck", "spba";
- dmas = <&sdma 17 20 1>, <&sdma 18 20 1>,
- <&sdma 19 20 1>, <&sdma 20 20 1>,
- <&sdma 21 20 1>, <&sdma 22 20 1>;
+ interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ASRC_IPG>,
+ <&clks IMX6SX_CLK_ASRC_MEM>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks IMX6SX_CLK_SPDIF>, <&clks 0>, <&clks 0>,
+ <&clks IMX6SX_CLK_SPBA>;
+ clock-names = "mem", "ipg", "asrck_0",
+ "asrck_1", "asrck_2", "asrck_3", "asrck_4",
+ "asrck_5", "asrck_6", "asrck_7", "asrck_8",
+ "asrck_9", "asrck_a", "asrck_b", "asrck_c",
+ "asrck_d", "asrck_e", "asrck_f", "spba";
+ dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+ <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
dma-names = "rxa", "rxb", "rxc",
- "txa", "txb", "txc";
+ "txa", "txb", "txc";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
status = "okay";
};
};
@@ -559,6 +655,12 @@
gpio-ranges = <&iomuxc 0 148 10>, <&iomuxc 10 169 2>;
};
+ mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
kpp: kpp@20b8000 {
compatible = "fsl,imx6sx-kpp", "fsl,imx21-kpp";
reg = <0x020b8000 0x4000>;
@@ -712,6 +814,20 @@
fsl,anatop = <&anatop>;
};
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
+ caam_snvs: caam-snvs@20cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x20cc000 0x4000>;
+ };
+
snvs: snvs@20cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -767,6 +883,7 @@
#interrupt-cells = <3>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x7c00000 0x3d00 0x0 0x400240>;
clocks = <&clks IMX6SX_CLK_IPG>;
clock-names = "ipg";
@@ -817,6 +934,30 @@
reg = <0x020e4000 0x4000>;
};
+ ldb: ldb@20e0014 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ldb", "fsl,imx53-ldb";
+ gpr = <&gpr>;
+ status = "disabled";
+ clocks = <&clks IMX6SX_CLK_LDB_DI0>,
+ <&clks IMX6SX_CLK_LCDIF1_SEL>,
+ <&clks IMX6SX_CLK_LCDIF2_SEL>,
+ <&clks IMX6SX_CLK_LDB_DI0_DIV_3_5>,
+ <&clks IMX6SX_CLK_LDB_DI0_DIV_7>,
+ <&clks IMX6SX_CLK_LDB_DI0_DIV_SEL>;
+ clock-names = "ldb_di0",
+ "di0_sel",
+ "di1_sel",
+ "ldb_di0_div_3_5",
+ "ldb_di0_div_7",
+ "ldb_di0_div_sel";
+ lvds-channel@0 {
+ reg = <0>;
+ status = "disabled";
+ };
+ };
+
sdma: sdma@20ec000 {
compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma";
reg = <0x020ec000 0x4000>;
@@ -928,6 +1069,8 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
fsl,num-rx-queues = <3>;
+ stop-mode = <&gpr 0x10 3>;
+ fsl,wakeup_irq = <0>;
status = "disabled";
};
@@ -949,6 +1092,8 @@
<&clks IMX6SX_CLK_USDHC1>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
status = "disabled";
};
@@ -961,6 +1106,8 @@
<&clks IMX6SX_CLK_USDHC2>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
status = "disabled";
};
@@ -973,6 +1120,8 @@
<&clks IMX6SX_CLK_USDHC3>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
status = "disabled";
};
@@ -985,6 +1134,8 @@
<&clks IMX6SX_CLK_USDHC4>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
status = "disabled";
};
@@ -1037,6 +1188,10 @@
<&clks IMX6SX_CLK_ENET_PTP>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
+ fsl,num-tx-queues=<3>;
+ fsl,num-rx-queues=<3>;
+ stop-mode = <&gpr 0x10 4>;
+ fsl,wakeup_irq = <0>;
status = "disabled";
};
@@ -1125,6 +1280,12 @@
status = "disabled";
};
+ qspi_m4: qspi-m4 {
+ compatible = "fsl,imx6sx-qspi-m4-restore";
+ reg = <0x021e4000 0x4000>;
+ status = "disabled";
+ };
+
uart2: serial@21e8000 {
compatible = "fsl,imx6sx-uart",
"fsl,imx6q-uart", "fsl,imx21-uart";
@@ -1203,21 +1364,46 @@
ranges;
csi1: csi@2214000 {
+ compatible = "fsl,imx6s-csi";
reg = <0x02214000 0x4000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
<&clks IMX6SX_CLK_CSI>,
<&clks IMX6SX_CLK_DCIC1>;
- clock-names = "disp-axi", "csi_mclk", "dcic";
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ power-domains = <&pd_disp>;
+ status = "disabled";
+ };
+
+ dcic1: dcic@220c000 {
+ compatible = "fsl,imx6sx-dcic";
+ reg = <0x220c000 0x4000>;
+ interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DCIC1>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "dcic", "disp-axi";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
+ dcic2: dcic@2210000 {
+ compatible = "fsl,imx6sx-dcic";
+ reg = <0x2210000 0x4000>;
+ interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DCIC2>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "dcic", "disp-axi";
+ gpr = <&gpr>;
status = "disabled";
};
pxp: pxp@2218000 {
- compatible = "fsl,imx6sx-pxp", "fsl,imx6ull-pxp";
+ compatible = "fsl,imx6sx-pxp-dma", "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
reg = <0x02218000 0x4000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SX_CLK_PXP_AXI>;
- clock-names = "axi";
+ clocks = <&clks IMX6SX_CLK_PXP_AXI>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pxp-axi", "disp-axi";
power-domains = <&pd_disp>;
status = "disabled";
};
@@ -1273,6 +1459,7 @@
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_IPG>;
clock-names = "adc";
+ num-channels = <4>;
fsl,adck-max-frequency = <30000000>, <40000000>,
<20000000>;
status = "disabled";
@@ -1284,6 +1471,7 @@
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_IPG>;
clock-names = "adc";
+ num-channels = <4>;
fsl,adck-max-frequency = <30000000>, <40000000>,
<20000000>;
status = "disabled";
@@ -1309,6 +1497,27 @@
status = "disabled";
};
+ sema4: sema4@02290000 { /* sema4 */
+ compatible = "fsl,imx6sx-sema4";
+ reg = <0x02290000 0x4000>;
+ interrupts = <0 116 0x04>;
+ status = "okay";
+ };
+
+ mu: mu@02294000 { /* mu */
+ compatible = "fsl,imx6sx-mu";
+ reg = <0x02294000 0x4000>;
+ interrupts = <0 90 0x04>;
+ #mbox-cells = <2>;
+ };
+
+ mu_lp: mu_lp@02294000 { /* mu */
+ compatible = "fsl,imx6sx-mu-lp";
+ reg = <0x02294000 0x4000>;
+ interrupts = <0 90 0x04>;
+ status = "okay";
+ };
+
uart6: serial@22a0000 {
compatible = "fsl,imx6sx-uart",
"fsl,imx6q-uart", "fsl,imx21-uart";
@@ -1392,4 +1601,18 @@
status = "disabled";
};
};
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx6sx-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";
+ };
};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi-oob.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi-oob.dts
new file mode 100644
index 000000000000..90e0045fa2e4
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi-oob.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017 NXP
+ *
+ * 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 "imx6ul-14x14-evk-btwifi.dts"
+#include "imx6ul-evk-btwifi-oob.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
new file mode 100644
index 000000000000..4613799a97c7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6ul-14x14-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-csi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-csi.dts
new file mode 100644
index 000000000000..9a1f453551d6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-csi.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
+
+#include "imx6ul-14x14-evk.dts"
+
+
+&csi {
+ status = "okay";
+};
+
+&ov5640 {
+ status = "okay";
+};
+
+&sim2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi-slave.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi-slave.dts
new file mode 100644
index 000000000000..16f82a32c2e2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi-slave.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 NXP
+
+/*
+ * DTS file for ECSPI Slave Certification at i.mx6ul 14x14 evk board.
+ * NOTE: Because Ethernet2 use the same pins with ecspi4, so disable
+ * fec1/fec2 for ECSPI4 test.
+ */
+
+#include "imx6ul-14x14-evk-ecspi.dts"
+
+/delete-node/&spidev0;
+
+&ecspi4 {
+ #address-cells = <0>;
+ spi-slave;
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi.dts
new file mode 100644
index 000000000000..7ca5e4224357
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-ecspi.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 NXP
+
+/*
+ * DTS file for ECSPI Certification at i.mx6ul 14x14 evk board.
+ * NOTE: Because Ethernet2 use the same pins with ecspi4, so disable
+ * fec1/fec2 for ECSPI4 test.
+ */
+
+#include "imx6ul-14x14-evk.dts"
+
+&iomuxc {
+ pinctrl_ecspi4: ecspi4grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET2_TX_DATA1__ECSPI4_SCLK 0x70a1
+ MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI 0x70a1
+ MX6UL_PAD_ENET2_TX_CLK__ECSPI4_MISO 0x70a1
+ MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0 0x70a1
+ >;
+ };
+};
+
+&ecspi4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4>;
+ status = "okay";
+
+ spidev0: spi@0 {
+ reg = <0>;
+ compatible = "rohm,dh2228fv";
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&fec1 {
+ status = "disabled";
+};
+
+&fec2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts
new file mode 100644
index 000000000000..bc4e53f25565
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6ul-14x14-evk.dts"
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts
new file mode 100644
index 000000000000..b7fe014619d4
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
+
+#include "imx6ul-14x14-evk.dts"
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay";
+ nand-on-flash-bbt;
+};
+
+&iomuxc {
+ pinctrl_gpmi_nand_1: gpmi-nand-1 {
+ fsl,pins = <
+ MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1
+ MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1
+ MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1
+ MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000
+ MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1
+ MX6UL_PAD_NAND_CE1_B__RAWNAND_CE1_B 0xb0b1
+ MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1
+ MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1
+ MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1
+ MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1
+ MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1
+ MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1
+ MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1
+ MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1
+ MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1
+ MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1
+ >;
+ };
+};
+
+&qspi {
+ status = "disabled";
+};
+
+&usdhc2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
index aa86341adaaa..9c8e1c938340 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
@@ -12,6 +12,19 @@
reg = <0x80000000 0x20000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0xa000000>;
+ linux,cma-default;
+ };
+ };
+
backlight_display: backlight-display {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
@@ -20,6 +33,10 @@
status = "okay";
};
+ pxp_v4l2 {
+ compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
reg_sd1_vmmc: regulator-sd1-vmmc {
compatible = "regulator-fixed";
@@ -27,6 +44,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
@@ -61,22 +79,63 @@
"LINPUT3", "Mic Jack",
"RINPUT1", "Mic Jack",
"RINPUT2", "Mic Jack";
+ status = "disabled";
simple-audio-card,cpu {
sound-dai = <&sai2>;
+ status = "disabled";
};
dailink_master: simple-audio-card,codec {
sound-dai = <&codec>;
clocks = <&clks IMX6UL_CLK_SAI2>;
+ status = "disabled";
};
};
+ sound-wm8960 {
+ compatible = "fsl,imx6ul-evk-wm8960",
+ "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec>;
+ asrc-controller = <&asrc>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ /*
+ * hp-det = <hp-det-pin hp-det-polarity>;
+ * hp-det-pin: JD1 JD2 or JD3
+ * hp-det-polarity = 0: hp detect high for headphone
+ * hp-det-polarity = 1: hp detect high for speaker
+ */
+ hp-det = <3 0>;
+ hp-det-gpios = <&gpio5 4 0>;
+ mic-det-gpios = <&gpio5 4 0>;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT2", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Main MIC",
+ "RINPUT2", "Main MIC",
+ "Mic Jack", "MICB",
+ "Main MIC", "MICB",
+ "CPU-Playback", "ASRC-Playback",
+ "Playback", "CPU-Playback",
+ "ASRC-Capture", "CPU-Capture",
+ "CPU-Capture", "Capture";
+ };
+
spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
status = "okay";
+ pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 0>;
cs-gpios = <&gpio5 7 0>;
@@ -90,20 +149,10 @@
#gpio-cells = <2>;
reg = <0>;
registers-number = <1>;
+ registers-default = /bits/ 8 <0x57>;
spi-max-frequency = <100000>;
};
};
-
- panel {
- compatible = "innolux,at043tn24";
- backlight = <&backlight_display>;
-
- port {
- panel_in: endpoint {
- remote-endpoint = <&display_out>;
- };
- };
- };
};
&clks {
@@ -111,6 +160,16 @@
assigned-clock-rates = <786432000>;
};
+&csi {
+ status = "disabled";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -122,6 +181,28 @@
compatible = "wlf,wm8960";
reg = <0x1a>;
wlf,shared-lrclk;
+ clocks = <&clks IMX6UL_CLK_SAI2>;
+ clock-names = "mclk";
+ };
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi1>;
+ clocks = <&clks IMX6UL_CLK_CSI>;
+ clock-names = "csi_mclk";
+ pwn-gpios = <&gpio_spi 6 1>;
+ rst-gpios = <&gpio_spi 5 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ status = "disabled";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
};
};
@@ -183,6 +264,15 @@
mag3110@e {
compatible = "fsl,mag3110";
reg = <0x0e>;
+ position = <2>;
+ };
+
+ fxls8471@1e {
+ compatible = "fsl,fxls8471";
+ reg = <0x1e>;
+ position = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <0 8>;
};
};
@@ -192,11 +282,31 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>;
+ display = <&display0>;
status = "okay";
- port {
- display_out: endpoint {
- remote-endpoint = <&panel_in>;
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
};
};
};
@@ -207,6 +317,10 @@
status = "okay";
};
+&pxp {
+ status = "okay";
+};
+
&qspi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi>;
@@ -242,6 +356,22 @@
status = "okay";
};
+&sim2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sim2>;
+ assigned-clocks = <&clks IMX6UL_CLK_SIM_SEL>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_SIM_PODF>;
+ assigned-clock-rates = <240000000>;
+ /* GPIO_ACTIVE_HIGH/LOW:sim card voltage control
+ * NCN8025:Vcc = ACTIVE_HIGH?5V:3V
+ * TDA8035:Vcc = ACTIVE_HIGH?5V:1.8V
+ */
+ pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
+ port = <1>;
+ sven_low_active;
+ status = "okay";
+};
+
&tsc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tsc>;
@@ -261,11 +391,16 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart2dte>; */
status = "okay";
};
&usbotg1 {
dr_mode = "otg";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
status = "okay";
};
@@ -298,7 +433,7 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- no-1-8-v;
+ non-removable;
keep-power-in-suspend;
wakeup-source;
status = "okay";
@@ -499,10 +634,25 @@
>;
};
+ pinctrl_uart2dte: uart2dtegrp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
- MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
@@ -547,6 +697,51 @@
>;
};
+ pinctrl_usdhc2_8bit: usdhc2grp_8bit {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
+ >;
+ };
+
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi-oob.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi-oob.dts
new file mode 100644
index 000000000000..8a8ece34d775
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi-oob.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017 NXP
+ *
+ * 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 "imx6ul-9x9-evk-btwifi.dts"
+#include "imx6ul-evk-btwifi-oob.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts
new file mode 100644
index 000000000000..de89052d97fc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6ul-9x9-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk-ldo.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-ldo.dts
new file mode 100644
index 000000000000..715efcb9512e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk-ldo.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6ul-9x9-evk.dts"
+
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 696000 1275000
+ 528000 1175000
+ 396000 1025000
+ 198000 950000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 696000 1275000
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <0>;
+};
+
+&gpc {
+ fsl,ldo-bypass = <0>; /* use ldo-enable, u-boot will check it and configure */
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk.dts b/arch/arm/boot/dts/imx6ul-9x9-evk.dts
new file mode 100644
index 000000000000..4350a2f4b257
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk.dts
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ul.dtsi"
+
+/ {
+ model = "Freescale i.MX6 UltraLite 9x9 EVK Board";
+ compatible = "fsl,imx6ul-9x9-evk", "fsl,imx6ul";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x10000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0xa000000>;
+ linux,cma-default;
+ };
+ };
+
+ pxp_v4l2 {
+ compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_can_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "can-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_gpio_dvfs: regulator-gpio {
+ compatible = "regulator-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dvfs>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "gpio_dvfs";
+ regulator-type = "voltage";
+ gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;
+ states = <1300000 0x1 1400000 0x0>;
+ };
+
+ reg_sd1_vmmc: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6ul-evk-wm8960",
+ "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec>;
+ asrc-controller = <&asrc>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ /*
+ * hp-det = <hp-det-pin hp-det-polarity>;
+ * hp-det-pin: JD1 JD2 or JD3
+ * hp-det-polarity = 0: hp detect high for headphone
+ * hp-det-polarity = 1: hp detect high for speaker
+ */
+ hp-det = <3 0>;
+ hp-det-gpios = <&gpio5 4 0>;
+ mic-det-gpios = <&gpio5 4 0>;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT2", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Main MIC",
+ "RINPUT2", "Main MIC",
+ "Mic Jack", "MICB",
+ "Main MIC", "MICB",
+ "CPU-Playback", "ASRC-Playback",
+ "Playback", "CPU-Playback",
+ "ASRC-Capture", "CPU-Capture",
+ "CPU-Capture", "Capture";
+ };
+
+ spi4 {
+ compatible = "spi-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi4>;
+ pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ gpio-sck = <&gpio5 11 0>;
+ gpio-mosi = <&gpio5 10 0>;
+ cs-gpios = <&gpio5 7 0>;
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio_spi: gpio_spi@0 {
+ compatible = "fairchild,74hc595";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ registers-number = <1>;
+ registers-default = /bits/ 8 <0x57>;
+ spi-max-frequency = <100000>;
+ };
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+ /*
+ * on i.MX6UL, no seperated VDD_ARM_IN and VDD_SOC_IN,
+ * to align with other platform and use the same cpufreq
+ * driver, still use the seperated OPP define for arm
+ * and soc.
+ */
+ operating-points = <
+ /* kHz uV */
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <1>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&csi {
+ status = "disabled";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ status = "okay";
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0xf>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze3000@8 {
+ compatible = "fsl,pfuze3000";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1a {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ /* use sw1c_reg to align with pfuze100/pfuze200 */
+ sw1c_reg: sw1b {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1475000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1650000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vldo2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vccsd {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: v33 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vldo4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ mag3110@e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ };
+
+ fxls8471@1e {
+ compatible = "fsl,fxls8471";
+ reg = <0x1e>;
+ position = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <0 8>;
+ };
+};
+
+&i2c2 {
+ clock_frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ codec: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&clks IMX6UL_CLK_SAI2>;
+ clock-names = "mclk";
+ wlf,shared-lrclk;
+ };
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi1>;
+ clocks = <&clks IMX6UL_CLK_CSI>;
+ clock-names = "csi_mclk";
+ pwn-gpios = <&gpio_spi 6 1>;
+ rst-gpios = <&gpio_spi 5 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ status = "disabled";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+ imx6ul-evk {
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_MCLK__CSI_MCLK 0x1b088
+ MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK 0x1b088
+ MX6UL_PAD_CSI_VSYNC__CSI_VSYNC 0x1b088
+ MX6UL_PAD_CSI_HSYNC__CSI_HSYNC 0x1b088
+ MX6UL_PAD_CSI_DATA00__CSI_DATA02 0x1b088
+ MX6UL_PAD_CSI_DATA01__CSI_DATA03 0x1b088
+ MX6UL_PAD_CSI_DATA02__CSI_DATA04 0x1b088
+ MX6UL_PAD_CSI_DATA03__CSI_DATA05 0x1b088
+ MX6UL_PAD_CSI_DATA04__CSI_DATA06 0x1b088
+ MX6UL_PAD_CSI_DATA05__CSI_DATA07 0x1b088
+ MX6UL_PAD_CSI_DATA06__CSI_DATA08 0x1b088
+ MX6UL_PAD_CSI_DATA07__CSI_DATA09 0x1b088
+ >;
+ };
+
+ pinctrl_dvfs: dvfsgrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x79
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x80000000
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp{
+ fsl,pins = <
+ MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
+ MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
+ MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
+ /* used for lcd reset */
+ MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x79
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
+ MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
+ MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
+ MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
+ MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
+ MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
+ MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
+ MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
+ MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
+ MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
+ MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
+ MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088
+ MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088
+ MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088
+ MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088
+ MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x17059
+ >;
+ };
+
+ pinctrl_sim2_1: sim2grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD 0xb808
+ MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK 0x31
+ MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0xb808
+ MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN 0xb808
+ MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD 0xb809
+ MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x3008
+ >;
+ };
+
+ pinctrl_spi4: spi4grp {
+ fsl,pins = <
+ MX6UL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1
+ MX6UL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1
+ MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1
+ MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000
+ >;
+ };
+
+ pinctrl_tsc: tscgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2dte: uart2dtegrp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 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
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17059
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+ ddrsmp=<0>;
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <0>;
+ };
+};
+
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+
+ assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+ <&clks IMX6UL_CLK_SAI2>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <12288000>;
+
+ status = "okay";
+};
+
+&sim2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sim2_1>;
+ assigned-clocks = <&clks IMX6UL_CLK_SIM_SEL>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_SIM_PODF>;
+ assigned-clock-rates = <240000000>;
+ pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
+ port = <1>;
+ sven_low_active;
+ status = "okay";
+};
+
+&tsc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc>;
+ xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+ measure_delay_time = <0xffff>;
+ pre_charge_time = <0xfff>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ fsl,uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart2dte>; */
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ no-1-8-v;
+ non-removable;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
diff --git a/arch/arm/boot/dts/imx6ul-evk-btwifi-oob.dtsi b/arch/arm/boot/dts/imx6ul-evk-btwifi-oob.dtsi
new file mode 100644
index 000000000000..e1f16574a24e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-evk-btwifi-oob.dtsi
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-2019 NXP
+ *
+ * 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.
+ */
+
+&pinctrl_wifi {
+ fsl,pins = <
+ /* MUXing for WL_HOST_WAKE */
+ MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x0b001 /* input: 100K Pull-up */
+ >;
+};
+
+/*
+ * For WL_HOST_WAKE (OOB_IRQ) to function correctly, we must disable
+ * the secondary ethernet port (FEC2). Hardware re-work is to remove
+ * R1633 and populate R1704 with 0 Ohm resistor.
+ * Refer to Murata Hardware Reference Manual for more details.
+ */
+&fec2 {
+ status = "disabled";
+};
+
+&brcmf {
+ interrupt-parent = <&gpio2>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>; /* M.2 WL_HOST_WAKE is active low */
+ interrupt-names = "host-wake";
+};
diff --git a/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi
new file mode 100644
index 000000000000..b3dfefec7fae
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ *
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into Slot
+ * SD1 and using Murata i.MX InterConnect Ver 2.0 Adapter. Bluetooth UART &
+ * control signals are connected via ribbon cable (J1701 connector).
+ */
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio_spi 4 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&iomuxc {
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x03029
+ >;
+ };
+};
+
+&reg_sd1_vmmc {
+ regulator-always-on;
+};
+
+&uart2 {
+ resets = <&modem_reset>;
+};
+
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ no-1-8-v;
+ non-removable;
+ pm-ignore-notify;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ cap-power-off-card;
+ /delete-property/ wakeup-source;
+ /delete-property/ enable-sdio-wakeup;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+&gpio_spi {
+ /* Murata: modify default setting so that BT_nPWD/BT_REG_ON
+ * is low (0V) during kernel boot.
+ */
+ registers-default = /bits/ 8 <0x47>;
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
index 4e99e6c79a68..5a3e06d6219b 100644
--- a/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
@@ -8,409 +8,10 @@
/dts-v1/;
#include "imx6ul-kontron-n6310-som.dtsi"
+#include "imx6ul-kontron-n6x1x-s.dtsi"
/ {
model = "Kontron N6310 S";
compatible = "kontron,imx6ul-n6310-s", "kontron,imx6ul-n6310-som",
"fsl,imx6ul";
-
- gpio-leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpio_leds>;
-
- led1 {
- label = "debug-led1";
- gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
- default-state = "off";
- linux,default-trigger = "heartbeat";
- };
-
- led2 {
- label = "debug-led2";
- gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
- default-state = "off";
- };
-
- led3 {
- label = "debug-led3";
- gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
- default-state = "off";
- };
- };
-
- pwm-beeper {
- compatible = "pwm-beeper";
- pwms = <&pwm8 0 5000>;
- };
-
- reg_3v3: regulator-3v3 {
- compatible = "regulator-fixed";
- regulator-name = "3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-
- reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
- compatible = "regulator-fixed";
- regulator-name = "usb_otg1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
-
- reg_vref_adc: regulator-vref-adc {
- compatible = "regulator-fixed";
- regulator-name = "vref-adc";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-};
-
-&adc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc1>;
- num-channels = <3>;
- vref-supply = <&reg_vref_adc>;
- status = "okay";
-};
-
-&can2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_flexcan2>;
- status = "okay";
-};
-
-&ecspi1 {
- cs-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi1>;
- status = "okay";
-
- eeprom@0 {
- compatible = "anvo,anv32e61w", "atmel,at25";
- reg = <0>;
- spi-max-frequency = <20000000>;
- spi-cpha;
- spi-cpol;
- pagesize = <1>;
- size = <8192>;
- address-width = <16>;
- };
-};
-
-&fec1 {
- pinctrl-0 = <&pinctrl_enet1>;
- /delete-node/ mdio;
-};
-
-&fec2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio>;
- phy-mode = "rmii";
- phy-handle = <&ethphy2>;
- status = "okay";
-
- mdio {
- #address-cells = <1>;
- #size-cells = <0>;
-
- ethphy1: ethernet-phy@1 {
- reg = <1>;
- micrel,led-mode = <0>;
- clocks = <&clks IMX6UL_CLK_ENET_REF>;
- clock-names = "rmii-ref";
- };
-
- ethphy2: ethernet-phy@2 {
- reg = <2>;
- micrel,led-mode = <0>;
- clocks = <&clks IMX6UL_CLK_ENET2_REF>;
- clock-names = "rmii-ref";
- };
- };
-};
-
-&i2c1 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1>;
- status = "okay";
-};
-
-&i2c4 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c4>;
- status = "okay";
-
- rtc@32 {
- compatible = "epson,rx8900";
- reg = <0x32>;
- };
-};
-
-&pwm8 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm8>;
- status = "okay";
-};
-
-&uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart1>;
- status = "okay";
-};
-
-&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart2>;
- linux,rs485-enabled-at-boot-time;
- rs485-rx-during-tx;
- rs485-rts-active-low;
- uart-has-rtscts;
- status = "okay";
-};
-
-&uart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart3>;
- fsl,uart-has-rtscts;
- status = "okay";
-};
-
-&uart4 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart4>;
- status = "okay";
-};
-
-&usbotg1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usbotg1>;
- dr_mode = "otg";
- srp-disable;
- hnp-disable;
- adp-disable;
- vbus-supply = <&reg_usb_otg1_vbus>;
- status = "okay";
-};
-
-&usbotg2 {
- dr_mode = "host";
- disable-over-current;
- status = "okay";
-};
-
-&usdhc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc1>;
- cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
- keep-power-in-suspend;
- wakeup-source;
- vmmc-supply = <&reg_3v3>;
- voltage-ranges = <3300 3300>;
- no-1-8-v;
- status = "okay";
-};
-
-&usdhc2 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- pinctrl-0 = <&pinctrl_usdhc2>;
- pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
- pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
- non-removable;
- keep-power-in-suspend;
- wakeup-source;
- vmmc-supply = <&reg_3v3>;
- voltage-ranges = <3300 3300>;
- no-1-8-v;
- status = "okay";
-};
-
-&wdog1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_wdog>;
- fsl,ext-reset-output;
- status = "okay";
-};
-
-&iomuxc {
- pinctrl-0 = <&pinctrl_reset_out &pinctrl_gpio>;
-
- pinctrl_adc1: adc1grp {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
- MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
- MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0xb0
- >;
- };
-
- /* FRAM */
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x100b1
- MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x100b1
- MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x100b1
- MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x100b1 /* ECSPI1-CS1 */
- >;
- };
-
- pinctrl_enet2: enet2grp {
- fsl,pins = <
- MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
- MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
- MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
- MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
- MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
- MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
- MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
- MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009
- >;
- };
-
- pinctrl_enet2_mdio: enet2mdiogrp {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
- MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
- >;
- };
-
- pinctrl_flexcan2: flexcan2grp{
- fsl,pins = <
- MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
- MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
- >;
- };
-
- pinctrl_gpio: gpiogrp {
- fsl,pins = <
- MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b0b0 /* DOUT1 */
- MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b0b0 /* DIN1 */
- MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0 /* DOUT2 */
- MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* DIN2 */
- >;
- };
-
- pinctrl_gpio_leds: gpioledsgrp {
- fsl,pins = <
- MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x1b0b0 /* LED H14 */
- MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0b0 /* LED H15 */
- MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0 /* LED H16 */
- >;
- };
-
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6UL_PAD_CSI_PIXCLK__I2C1_SCL 0x4001b8b0
- MX6UL_PAD_CSI_MCLK__I2C1_SDA 0x4001b8b0
- >;
- };
-
- pinctrl_i2c4: i2c4grp {
- fsl,pins = <
- MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001f8b0
- MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001f8b0
- >;
- };
-
- pinctrl_pwm8: pwm8grp {
- fsl,pins = <
- MX6UL_PAD_CSI_HSYNC__PWM8_OUT 0x110b0
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
- MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
- >;
- };
-
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6UL_PAD_NAND_DATA04__UART2_DCE_TX 0x1b0b1
- MX6UL_PAD_NAND_DATA05__UART2_DCE_RX 0x1b0b1
- MX6UL_PAD_NAND_DATA06__UART2_DCE_CTS 0x1b0b1
- /*
- * mux unused RTS to make sure it doesn't cause
- * any interrupts when it is undefined
- */
- MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS 0x1b0b1
- >;
- };
-
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1
- MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
- MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1
- MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1
- >;
- };
-
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1
- MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1
- >;
- };
-
- pinctrl_usbotg1: usbotg1 {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0
- >;
- };
-
- pinctrl_usdhc1: usdhc1grp {
- fsl,pins = <
- MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
- MX6UL_PAD_SD1_CLK__USDHC1_CLK 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_UART1_RTS_B__GPIO1_IO19 0x100b1 /* SD1_CD */
- >;
- };
-
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
- MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
- MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
- MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
- MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
- MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
- >;
- };
-
- pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
- fsl,pins = <
- MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
- MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
- MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
- MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
- MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
- MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
- >;
- };
-
- pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
- fsl,pins = <
- MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
- MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
- MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
- MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
- MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
- MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
- >;
- };
-
- pinctrl_wdog: wdoggrp {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY 0x30b0
- >;
- };
};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi
index a896b2348dd2..47d3ce5d255f 100644
--- a/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi
@@ -6,7 +6,7 @@
*/
#include "imx6ul.dtsi"
-#include <dt-bindings/gpio/gpio.h>
+#include "imx6ul-kontron-n6x1x-som-common.dtsi"
/ {
model = "Kontron N6310 SOM";
@@ -18,49 +18,7 @@
};
};
-&ecspi2 {
- cs-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi2>;
- status = "okay";
-
- spi-flash@0 {
- compatible = "mxicy,mx25v8035f", "jedec,spi-nor";
- spi-max-frequency = <50000000>;
- reg = <0>;
- };
-};
-
-&fec1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio>;
- phy-mode = "rmii";
- phy-handle = <&ethphy1>;
- status = "okay";
-
- mdio {
- #address-cells = <1>;
- #size-cells = <0>;
-
- ethphy1: ethernet-phy@1 {
- reg = <1>;
- micrel,led-mode = <0>;
- clocks = <&clks IMX6UL_CLK_ENET_REF>;
- clock-names = "rmii-ref";
- };
- };
-};
-
-&fec2 {
- phy-mode = "rmii";
- status = "disabled";
-};
-
&qspi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_qspi>;
- status = "okay";
-
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
@@ -81,54 +39,3 @@
};
};
};
-
-&iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_reset_out>;
-
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x100b1
- MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x100b1
- MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x100b1
- MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x100b1
- >;
- };
-
- pinctrl_enet1: enet1grp {
- fsl,pins = <
- MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
- MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
- MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
- MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
- MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
- MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
- MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
- MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
- >;
- };
-
- pinctrl_enet1_mdio: enet1mdiogrp {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0
- MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0
- >;
- };
-
- pinctrl_qspi: qspigrp {
- fsl,pins = <
- MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
- MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
- MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
- MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
- MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
- MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
- >;
- };
-
- pinctrl_reset_out: rstoutgrp {
- fsl,pins = <
- MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b0b0
- >;
- };
-};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6311-s.dts b/arch/arm/boot/dts/imx6ul-kontron-n6311-s.dts
new file mode 100644
index 000000000000..239a1af3aeaa
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6311-s.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+
+#include "imx6ul-kontron-n6311-som.dtsi"
+#include "imx6ul-kontron-n6x1x-s.dtsi"
+
+/ {
+ model = "Kontron N6311 S";
+ compatible = "kontron,imx6ul-n6311-s", "kontron,imx6ul-n6311-som",
+ "fsl,imx6ul";
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6311-som.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6311-som.dtsi
new file mode 100644
index 000000000000..a095a7654ac6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6311-som.dtsi
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ */
+
+#include "imx6ul.dtsi"
+#include "imx6ul-kontron-n6x1x-som-common.dtsi"
+
+/ {
+ model = "Kontron N6311 SOM";
+ compatible = "kontron,imx6ul-n6311-som", "fsl,imx6ul";
+
+ memory@80000000 {
+ reg = <0x80000000 0x20000000>;
+ device_type = "memory";
+ };
+};
+
+&qspi {
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-max-frequency = <104000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ reg = <0>;
+
+ partition@0 {
+ label = "ubi1";
+ reg = <0x00000000 0x08000000>;
+ };
+
+ partition@8000000 {
+ label = "ubi2";
+ reg = <0x08000000 0x18000000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6x1x-s.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6x1x-s.dtsi
new file mode 100644
index 000000000000..f05e91841202
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6x1x-s.dtsi
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ * Copyright (c) 2019 Krzysztof Kozlowski <krzk@kernel.org>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led1 {
+ label = "debug-led1";
+ gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led2 {
+ label = "debug-led2";
+ gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led3 {
+ label = "debug-led3";
+ gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+
+ pwm-beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm8 0 5000>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_vref_adc: regulator-vref-adc {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-adc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&adc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+ num-channels = <3>;
+ vref-supply = <&reg_vref_adc>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ status = "okay";
+
+ eeprom@0 {
+ compatible = "anvo,anv32e61w", "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ spi-cpha;
+ spi-cpol;
+ pagesize = <1>;
+ size = <8192>;
+ address-width = <16>;
+ };
+};
+
+&fec1 {
+ pinctrl-0 = <&pinctrl_enet1>;
+ /delete-node/ mdio;
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy2>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ };
+
+ ethphy2: ethernet-phy@2 {
+ reg = <2>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET2_REF>;
+ clock-names = "rmii-ref";
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ rtc@32 {
+ compatible = "epson,rx8900";
+ reg = <0x32>;
+ };
+};
+
+&pwm8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm8>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ linux,rs485-enabled-at-boot-time;
+ rs485-rx-during-tx;
+ rs485-rts-active-low;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbotg1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ over-current-active-low;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ vbus-supply = <&reg_5v>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3>;
+ voltage-ranges = <3300 3300>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ non-removable;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3>;
+ voltage-ranges = <3300 3300>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_reset_out &pinctrl_gpio>;
+
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
+ MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0xb0
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x100b1
+ MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x100b1
+ MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x100b1
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x100b1 /* ECSPI1-CS1 */
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009
+ >;
+ };
+
+ pinctrl_enet2_mdio: enet2mdiogrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_gpio: gpiogrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b0b0 /* DOUT1 */
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b0b0 /* DIN1 */
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0 /* DOUT2 */
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* DIN2 */
+ >;
+ };
+
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x1b0b0 /* LED H14 */
+ MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0b0 /* LED H15 */
+ MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0 /* LED H16 */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_PIXCLK__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_CSI_MCLK__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001f8b0
+ MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001f8b0
+ >;
+ };
+
+ pinctrl_pwm8: pwm8grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__PWM8_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DATA04__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_NAND_DATA05__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_NAND_DATA06__UART2_DCE_CTS 0x1b0b1
+ /*
+ * mux unused RTS to make sure it doesn't cause
+ * any interrupts when it is undefined
+ */
+ MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1
+ MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1 {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 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_UART1_RTS_B__GPIO1_IO19 0x100b1 /* SD1_CD */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6x1x-som-common.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6x1x-som-common.dtsi
new file mode 100644
index 000000000000..a17af4d9bfdf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-kontron-n6x1x-som-common.dtsi
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ * Copyright (c) 2019 Krzysztof Kozlowski <krzk@kernel.org>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ chosen {
+ stdout-path = &uart4;
+ };
+};
+
+&ecspi2 {
+ cs-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+
+ spi-flash@0 {
+ compatible = "mxicy,mx25v8035f", "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ micrel,led-mode = <0>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ };
+ };
+};
+
+&fec2 {
+ phy-mode = "rmii";
+ status = "disabled";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reset_out>;
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x100b1
+ MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x100b1
+ MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x100b1
+ MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x100b1
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
+ >;
+ };
+
+ pinctrl_enet1_mdio: enet1mdiogrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
+ MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
+ MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
+ MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
+ MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
+ MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
+ >;
+ };
+
+ pinctrl_reset_out: rstoutgrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b0b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index f008036e9294..3a9985cb0dd9 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -82,10 +82,15 @@
<&clks IMX6UL_CA7_SECONDARY_SEL>,
<&clks IMX6UL_CLK_STEP>,
<&clks IMX6UL_CLK_PLL1_SW>,
- <&clks IMX6UL_CLK_PLL1_SYS>;
+ <&clks IMX6UL_CLK_PLL1_SYS>,
+ <&clks IMX6UL_PLL1_BYPASS>,
+ <&clks IMX6UL_CLK_PLL1>,
+ <&clks IMX6UL_PLL1_BYPASS_SRC>,
+ <&clks IMX6UL_CLK_OSC>;
clock-names = "arm", "pll2_bus", "pll2_pfd2_396m",
"secondary_sel", "step", "pll1_sw",
- "pll1_sys";
+ "pll1_sys", "pll1_bypass", "pll1",
+ "pll1_bypass_src", "osc";
arm-supply = <&reg_arm>;
soc-supply = <&reg_soc>;
nvmem-cells = <&cpu_speed_grade>;
@@ -154,9 +159,43 @@
interrupt-parent = <&gpc>;
ranges;
- ocram: sram@900000 {
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6UL_CLK_PLL2_PFD2>, <&clks IMX6UL_CLK_PLL2_198M>,
+ <&clks IMX6UL_CLK_PLL2_BUS>, <&clks IMX6UL_CLK_ARM>,
+ <&clks IMX6UL_CLK_PLL3_USB_OTG>, <&clks IMX6UL_CLK_PERIPH>,
+ <&clks IMX6UL_CLK_PERIPH_PRE>, <&clks IMX6UL_CLK_PERIPH_CLK2>,
+ <&clks IMX6UL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6UL_CLK_OSC>,
+ <&clks IMX6UL_CLK_AHB>, <&clks IMX6UL_CLK_AXI>,
+ <&clks IMX6UL_CLK_PERIPH2>, <&clks IMX6UL_CLK_PERIPH2_PRE>,
+ <&clks IMX6UL_CLK_PERIPH2_CLK2>, <&clks IMX6UL_CLK_PERIPH2_CLK2_SEL>,
+ <&clks IMX6UL_CLK_STEP>, <&clks IMX6UL_CLK_MMDC_P0_FAST>;
+ clock-names = "pll2_pfd2_396m", "pll2_198m", "pll2_bus", "arm", "pll3_usb_otg",
+ "periph", "periph_pre", "periph_clk2", "periph_clk2_sel", "osc",
+ "ahb", "ocram", "periph2", "periph2_pre", "periph2_clk2", "periph2_clk2_sel",
+ "step", "mmdc";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ ocrams: sram@900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x900000 0x4000>;
+ };
+
+ ocrams_ddr: sram@904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x904000 0x1000>;
+ };
+
+ ocram: sram@905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x00905000 0x1B000>;
+ };
+
+ ocram_optee: sram@918000 {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x918000 0x8000>;
+ overw_reg = <&ocram 0x905000 0x13000>;
};
intc: interrupt-controller@a01000 {
@@ -184,6 +223,11 @@
clocks = <&clks IMX6UL_CLK_APBHDMA>;
};
+ caam_sm: caam-sm@100000 {
+ compatible = "fsl,imx7d-caam-sm", "fsl,imx6q-caam-sm";
+ reg = <0x100000 0x8000>;
+ };
+
gpmi: gpmi-nand@1806000 {
compatible = "fsl,imx6q-gpmi-nand";
#address-cells = <1>;
@@ -351,6 +395,31 @@
dma-names = "rx", "tx";
status = "disabled";
};
+
+ asrc: asrc@2034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x2034000 0x4000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ASRC_IPG>,
+ <&clks IMX6UL_CLK_ASRC_MEM>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks IMX6UL_CLK_SPDIF>, <&clks 0>, <&clks 0>,
+ <&clks IMX6UL_CLK_SPBA>;
+ clock-names = "mem", "ipg", "asrck_0",
+ "asrck_1", "asrck_2", "asrck_3", "asrck_4",
+ "asrck_5", "asrck_6", "asrck_7", "asrck_8",
+ "asrck_9", "asrck_a", "asrck_b", "asrck_c",
+ "asrck_d", "asrck_e", "asrck_f", "spba";
+ dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+ <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+ dma-names = "rxa", "rxb", "rxc",
+ "txa", "txb", "txc";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
+ status = "okay";
+ };
};
tsc: tsc@2040000 {
@@ -520,6 +589,9 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <1>;
fsl,num-rx-queues = <1>;
+ stop-mode = <&gpr 0x10 4>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
status = "disabled";
};
@@ -631,6 +703,20 @@
fsl,anatop = <&anatop>;
};
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
+ caam_snvs: caam-snvs@20cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x20cc000 0x4000>;
+ };
+
snvs: snvs@20cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -691,6 +777,7 @@
#interrupt-cells = <3>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x7c00000 0x7d00 0x0 0x1400640>;
};
iomuxc: iomuxc@20e0000 {
@@ -855,6 +942,16 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <1>;
fsl,num-rx-queues = <1>;
+ stop-mode = <&gpr 0x10 3>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
+ status = "disabled";
+ };
+
+ sim1: sim@0218c000 {
+ compatible = "fsl,imx6ul-sim";
+ reg = <0x0218c000 0x4000>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -934,6 +1031,15 @@
clocks = <&clks IMX6UL_CLK_MMDC_P0_IPG>;
};
+ sim2: sim@021b4000 {
+ compatible = "fsl,imx6ul-sim";
+ reg = <0x021b4000 0x4000>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_SIM2>;
+ clock-names = "sim";
+ status = "disabled";
+ };
+
weim: weim@21b8000 {
#address-cells = <2>;
#size-cells = <1>;
@@ -966,11 +1072,13 @@
};
csi: csi@21c4000 {
- compatible = "fsl,imx6ul-csi", "fsl,imx7-csi";
+ compatible = "fsl,imx6ul-csi", "fsl,imx7-csi", "fsl,imx6s-csi";
reg = <0x021c4000 0x4000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6UL_CLK_CSI>;
- clock-names = "mclk";
+ clocks = <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_CSI>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
status = "disabled";
};
@@ -986,11 +1094,13 @@
};
pxp: pxp@21cc000 {
- compatible = "fsl,imx6ul-pxp";
- reg = <0x021cc000 0x4000>;
+ compatible = "fsl,imx6ul-pxp-dma", "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
+ reg = <0x21cc000 0x4000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6UL_CLK_PXP>;
- clock-names = "axi";
+ clocks = <&clks IMX6UL_CLK_PXP>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "pxp-axi", "disp-axi";
+ status = "disabled";
};
qspi: spi@21e0000 {
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi-oob.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi-oob.dts
new file mode 100644
index 000000000000..85ea147de16f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi-oob.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017 NXP
+ *
+ * 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 "imx6ull-14x14-evk-btwifi.dts"
+#include "imx6ul-evk-btwifi-oob.dtsi"
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dts
new file mode 100644
index 000000000000..8a0a85d2e197
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6ull-14x14-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts
new file mode 100644
index 000000000000..d6dc9121b747
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6ull-14x14-evk.dts"
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts
new file mode 100644
index 000000000000..4391182e613c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2016 Freescale Semiconductor, Inc.
+
+#include "imx6ull-14x14-evk.dts"
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay";
+ nand-on-flash-bbt;
+};
+
+&iomuxc {
+ pinctrl_gpmi_nand_1: gpmi-nand-1 {
+ fsl,pins = <
+ MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1
+ MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1
+ MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1
+ MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000
+ MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1
+ MX6UL_PAD_NAND_CE1_B__RAWNAND_CE1_B 0xb0b1
+ MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1
+ MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1
+ MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1
+ MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1
+ MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1
+ MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1
+ MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1
+ MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1
+ MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1
+ MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1
+ >;
+ };
+};
+
+&qspi {
+ status = "disabled";
+};
+
+&usdhc2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
index 74aaa8a56a3d..bb8f91034db4 100644
--- a/arch/arm/boot/dts/imx6ull-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
@@ -8,11 +8,22 @@
#include "imx6ul-14x14-evk.dtsi"
/ {
- model = "Freescale i.MX6 UltraLiteLite 14x14 EVK Board";
+ model = "Freescale i.MX6 ULL 14x14 EVK Board";
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
};
&clks {
- assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>;
- assigned-clock-rates = <320000000>;
+ assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
+ <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <320000000>, <786432000>;
};
+
+&csi {
+ status = "okay";
+};
+
+&ov5640 {
+ status = "okay";
+};
+
+/delete-node/ &sim2;
diff --git a/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi-oob.dts b/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi-oob.dts
new file mode 100644
index 000000000000..8d00a908ee94
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi-oob.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017 NXP
+ *
+ * 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 "imx6ull-9x9-evk-btwifi.dts"
+#include "imx6ul-evk-btwifi-oob.dtsi"
diff --git a/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi.dts b/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi.dts
new file mode 100644
index 000000000000..c8a51006213f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-9x9-evk-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx6ull-9x9-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ull-9x9-evk-ldo.dts b/arch/arm/boot/dts/imx6ull-9x9-evk-ldo.dts
new file mode 100644
index 000000000000..a878fe5bbb78
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-9x9-evk-ldo.dts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 NXP.
+ *
+ * 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 "imx6ull-9x9-evk.dts"
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 528000 1175000
+ 396000 1025000
+ 198000 950000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <0>;
+};
+
+&gpc {
+ fsl,ldo-bypass = <0>; /* use ldo-enable, u-boot will check it and configure */
+};
+
+&reg_arm {
+ /delete-property/ vin-supply;
+};
+
+&reg_soc {
+ /delete-property/ vin-supply;
+};
diff --git a/arch/arm/boot/dts/imx6ull-9x9-evk.dts b/arch/arm/boot/dts/imx6ull-9x9-evk.dts
new file mode 100644
index 000000000000..9514086b21c8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-9x9-evk.dts
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ull.dtsi"
+
+/ {
+ model = "Freescale i.MX6 ULL 9x9 EVK Board";
+ compatible = "fsl,imx6ull-9x9-evk", "fsl,imx6ull";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x10000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0xa000000>;
+ linux,cma-default;
+ };
+ };
+
+ pxp_v4l2 {
+ compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_can_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "can-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_gpio_dvfs: regulator-gpio {
+ compatible = "regulator-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dvfs>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "gpio_dvfs";
+ regulator-type = "voltage";
+ gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;
+ states = <1300000 0x1 1400000 0x0>;
+ };
+
+ reg_sd1_vmmc: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6ul-evk-wm8960",
+ "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec>;
+ asrc-controller = <&asrc>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ /*
+ * hp-det = <hp-det-pin hp-det-polarity>;
+ * hp-det-pin: JD1 JD2 or JD3
+ * hp-det-polarity = 0: hp detect high for headphone
+ * hp-det-polarity = 1: hp detect high for speaker
+ */
+ hp-det = <3 0>;
+ hp-det-gpios = <&gpio5 4 0>;
+ mic-det-gpios = <&gpio5 4 0>;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT2", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Main MIC",
+ "RINPUT2", "Main MIC",
+ "Mic Jack", "MICB",
+ "Main MIC", "MICB",
+ "CPU-Playback", "ASRC-Playback",
+ "Playback", "CPU-Playback",
+ "ASRC-Capture", "CPU-Capture",
+ "CPU-Capture", "Capture";
+ };
+
+ spi4 {
+ compatible = "spi-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi4>;
+ pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ gpio-sck = <&gpio5 11 0>;
+ gpio-mosi = <&gpio5 10 0>;
+ cs-gpios = <&gpio5 7 0>;
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio_spi: gpio_spi@0 {
+ compatible = "fairchild,74hc595";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ registers-number = <1>;
+ registers-default = /bits/ 8 <0x57>;
+ spi-max-frequency = <100000>;
+ };
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+ /*
+ * on i.MX6ULL, no seperated VDD_ARM_IN and VDD_SOC_IN,
+ * to align with other platform and use the same cpufreq
+ * driver, still use the seperated OPP define for arm
+ * and soc.
+ */
+ operating-points = <
+ /* kHz uV */
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <1>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&csi {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ status = "okay";
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0xf>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze3000@8 {
+ compatible = "fsl,pfuze3000";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1a {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ /* use sw1c_reg to align with pfuze100/pfuze200 */
+ sw1c_reg: sw1b {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1475000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1650000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vldo2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vccsd {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: v33 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vldo4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ mag3110@e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ };
+
+ fxls8471@1e {
+ compatible = "fsl,fxls8471";
+ reg = <0x1e>;
+ position = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <0 8>;
+ };
+};
+
+&i2c2 {
+ clock_frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ codec: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&clks IMX6UL_CLK_SAI2>;
+ clock-names = "mclk";
+ wlf,shared-lrclk;
+ };
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi1>;
+ clocks = <&clks IMX6UL_CLK_CSI>;
+ clock-names = "csi_mclk";
+ pwn-gpios = <&gpio_spi 6 1>;
+ rst-gpios = <&gpio_spi 5 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ status = "okay";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+ imx6ul-evk {
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_MCLK__CSI_MCLK 0x1b088
+ MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK 0x1b088
+ MX6UL_PAD_CSI_VSYNC__CSI_VSYNC 0x1b088
+ MX6UL_PAD_CSI_HSYNC__CSI_HSYNC 0x1b088
+ MX6UL_PAD_CSI_DATA00__CSI_DATA02 0x1b088
+ MX6UL_PAD_CSI_DATA01__CSI_DATA03 0x1b088
+ MX6UL_PAD_CSI_DATA02__CSI_DATA04 0x1b088
+ MX6UL_PAD_CSI_DATA03__CSI_DATA05 0x1b088
+ MX6UL_PAD_CSI_DATA04__CSI_DATA06 0x1b088
+ MX6UL_PAD_CSI_DATA05__CSI_DATA07 0x1b088
+ MX6UL_PAD_CSI_DATA06__CSI_DATA08 0x1b088
+ MX6UL_PAD_CSI_DATA07__CSI_DATA09 0x1b088
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp{
+ fsl,pins = <
+ MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
+ MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
+ MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
+ MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
+ MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
+ MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
+ MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
+ MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
+ MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_qspi: qspigrp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1
+ MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
+ MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1
+ MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1
+ MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1
+ MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088
+ MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088
+ MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088
+ MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088
+ MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088
+ >;
+ };
+
+ pinctrl_tsc: tscgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2dte: uart2dtegrp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS 0x1b0b1
+ MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 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
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17059
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+ };
+};
+
+&iomuxc_snvs {
+ pinctrl-names = "default_snvs";
+ pinctrl-0 = <&pinctrl_hog_2>;
+ imx6ull-evk {
+ pinctrl_hog_2: hoggrp-2 {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x80000000
+ >;
+ };
+
+ pinctrl_dvfs: dvfsgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x79
+ >;
+ };
+
+ pinctrl_lcdif_reset: lcdifresetgrp {
+ fsl,pins = <
+ /* used for lcd reset */
+ MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x79
+ >;
+ };
+
+ pinctrl_spi4: spi4grp {
+ fsl,pins = <
+ MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1
+ MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1
+ MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1
+ MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000
+ >;
+ };
+
+ pinctrl_sai2_hp_det_b: sai2_hp_det_grp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x17059
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl
+ &pinctrl_lcdif_reset>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+ ddrsmp=<0>;
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <0>;
+ };
+};
+
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2
+ &pinctrl_sai2_hp_det_b>;
+
+ assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+ <&clks IMX6UL_CLK_SAI2>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <12288000>;
+
+ status = "okay";
+};
+
+&tsc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc>;
+ xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+ measure_delay_time = <0xffff>;
+ pre_charge_time = <0xfff>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ fsl,uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart2dte>; */
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ no-1-8-v;
+ non-removable;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
diff --git a/arch/arm/boot/dts/imx6ull-kontron-n6411-s.dts b/arch/arm/boot/dts/imx6ull-kontron-n6411-s.dts
new file mode 100644
index 000000000000..57588a5e1e34
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-kontron-n6411-s.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2019 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+
+#include "imx6ull-kontron-n6411-som.dtsi"
+#include "imx6ul-kontron-n6x1x-s.dtsi"
+
+/ {
+ model = "Kontron N6411 S";
+ compatible = "kontron,imx6ull-n6411-s", "kontron,imx6ull-n6411-som",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-kontron-n6411-som.dtsi b/arch/arm/boot/dts/imx6ull-kontron-n6411-som.dtsi
new file mode 100644
index 000000000000..b7e984284e1a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-kontron-n6411-som.dtsi
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ */
+
+#include "imx6ull.dtsi"
+#include "imx6ul-kontron-n6x1x-som-common.dtsi"
+
+/ {
+ model = "Kontron N6411 SOM";
+ compatible = "kontron,imx6ull-n6311-som", "fsl,imx6ull";
+
+ memory@80000000 {
+ reg = <0x80000000 0x20000000>;
+ device_type = "memory";
+ };
+};
+
+&qspi {
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-max-frequency = <104000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ reg = <0>;
+
+ partition@0 {
+ label = "ubi1";
+ reg = <0x00000000 0x08000000>;
+ };
+
+ partition@8000000 {
+ label = "ubi2";
+ reg = <0x08000000 0x18000000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
index b7e67d121322..f9ce39bf55be 100644
--- a/arch/arm/boot/dts/imx6ull.dtsi
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -13,6 +13,7 @@
&cpu0 {
clock-frequency = <900000000>;
+ fsl,low-power-run;
operating-points = <
/* kHz uV */
900000 1275000
@@ -36,21 +37,50 @@
};
&pxp {
- compatible = "fsl,imx6ull-pxp";
+ compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_PXP>;
+ clock-names = "pxp_ipg", "pxp_axi";
+ status = "disabled";
};
&usdhc1 {
compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
+ assigned-clocks = <&clks IMX6UL_CLK_USDHC1_SEL>, <&clks IMX6UL_CLK_USDHC1>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
+ assigned-clock-rates = <0>, <132000000>;
};
&usdhc2 {
compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
+ assigned-clocks = <&clks IMX6UL_CLK_USDHC2_SEL>, <&clks IMX6UL_CLK_USDHC2>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
+ assigned-clock-rates = <0>, <132000000>;
};
/ {
soc {
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ clocks = <&clks IMX6UL_CLK_PLL2_PFD2>, <&clks IMX6UL_CLK_PLL2_198M>,
+ <&clks IMX6UL_CLK_PLL2_BUS>, <&clks IMX6UL_CLK_ARM>,
+ <&clks IMX6UL_CLK_PLL3_USB_OTG>, <&clks IMX6UL_CLK_PERIPH>,
+ <&clks IMX6UL_CLK_PERIPH_PRE>, <&clks IMX6UL_CLK_PERIPH_CLK2>,
+ <&clks IMX6UL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6UL_CLK_OSC>,
+ <&clks IMX6UL_CLK_AHB>, <&clks IMX6UL_CLK_AXI>,
+ <&clks IMX6UL_CLK_PERIPH2>, <&clks IMX6UL_CLK_PERIPH2_PRE>,
+ <&clks IMX6UL_CLK_PERIPH2_CLK2>, <&clks IMX6UL_CLK_PERIPH2_CLK2_SEL>,
+ <&clks IMX6UL_CLK_STEP>, <&clks IMX6UL_CLK_MMDC_P0_FAST>, <&clks IMX6UL_PLL1_BYPASS_SRC>,
+ <&clks IMX6UL_PLL1_BYPASS>, <&clks IMX6UL_CLK_PLL1_SYS>, <&clks IMX6UL_CLK_PLL1_SW>,
+ <&clks IMX6UL_CLK_PLL1>;
+ clock-names = "pll2_pfd2_396m", "pll2_198m", "pll2_bus", "arm", "pll3_usb_otg",
+ "periph", "periph_pre", "periph_clk2", "periph_clk2_sel", "osc",
+ "ahb", "ocram", "periph2", "periph2_pre", "periph2_clk2", "periph2_clk2_sel",
+ "step", "mmdc", "pll1_bypass_src", "pll1_bypass", "pll1_sys", "pll1_sw", "pll1";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
aips3: aips-bus@2200000 {
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
@@ -68,6 +98,13 @@
clock-names = "dcp";
};
+ rngb: rng@2284000 {
+ compatible = "fsl,imx25-rngb";
+ reg = <0x02284000 0x4000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>;
+ };
+
iomuxc_snvs: iomuxc-snvs@2290000 {
compatible = "fsl,imx6ull-iomuxc-snvs";
reg = <0x02290000 0x4000>;
@@ -83,6 +120,18 @@
clock-names = "ipg", "per";
status = "disabled";
};
+
+ epdc: epdc@228c000 {
+ compatible = "fsl,imx7d-epdc";
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x228c000 0x4000>;
+ clocks = <&clks IMX6ULL_CLK_EPDC_ACLK>,
+ <&clks IMX6ULL_CLK_EPDC_PIX>;
+ clock-names = "epdc_axi", "epdc_pix";
+ /* Need to fix epdc-ram */
+ /* epdc-ram = <&gpr 0x4 30>; */
+ status = "disabled";
+ };
};
};
};
diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ulz-14x14-evk-btwifi.dts
new file mode 100644
index 000000000000..bac48ee3ae95
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ulz-14x14-evk-btwifi.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * 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 "imx6ulz-14x14-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk-emmc.dts b/arch/arm/boot/dts/imx6ulz-14x14-evk-emmc.dts
new file mode 100644
index 000000000000..e477952759ea
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ulz-14x14-evk-emmc.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx6ulz-14x14-evk.dts"
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk-gpmi-weim.dts b/arch/arm/boot/dts/imx6ulz-14x14-evk-gpmi-weim.dts
new file mode 100644
index 000000000000..12635e83e348
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ulz-14x14-evk-gpmi-weim.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2018 NXP
+
+#include "imx6ulz-14x14-evk.dts"
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay";
+ nand-on-flash-bbt;
+};
+
+&iomuxc {
+ pinctrl_gpmi_nand_1: gpmi-nand-1 {
+ fsl,pins = <
+ MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1
+ MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1
+ MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1
+ MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000
+ MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1
+ MX6UL_PAD_NAND_CE1_B__RAWNAND_CE1_B 0xb0b1
+ MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1
+ MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1
+ MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1
+ MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1
+ MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1
+ MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1
+ MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1
+ MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1
+ MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1
+ MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1
+ >;
+ };
+};
+
+&qspi {
+ status = "disabled";
+};
+
+&usdhc2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk.dts b/arch/arm/boot/dts/imx6ulz-14x14-evk.dts
index 483d9732c002..7deda307425b 100644
--- a/arch/arm/boot/dts/imx6ulz-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ulz-14x14-evk.dts
@@ -20,3 +20,20 @@
/delete-node/ panel;
};
+
+&iomuxc {
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
+ 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_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ >;
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-val-sai.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-val-sai.dts
new file mode 100644
index 000000000000..a256004559c4
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-val-sai.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ */
+
+#include "imx7d-12x12-lpddr3-val.dts"
+
+/ {
+ sound {
+ compatible = "fsl,imx7d-12x12-lpddr3-arm2-wm8958",
+ "fsl,imx-audio-wm8958";
+ model = "wm8958-audio";
+ cpu-dai = <&sai1>;
+ audio-codec = <&codec>;
+ codec-master;
+ hp-det-gpios = <&gpio1 12 1>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_headphone_det>;
+ pinctrl-1 = <&pinctrl_hog_1 &pinctrl_hog_sd2_vselect>;
+};
+
+&sai1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_sai1>;
+ pinctrl-1 = <&pinctrl_sai1>;
+ status = "okay";
+};
+
+&sdma {
+ status = "okay";
+};
+
+&sim1 {
+ status = "disabled";
+};
+
+&usdhc2 {
+ no-1-8-v;
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-val.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-val.dts
new file mode 100644
index 000000000000..422e60865b1a
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-val.dts
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ */
+
+/dts-v1/;
+
+#include "imx7d.dtsi"
+
+/ {
+ model = "Freescale i.MX7D LPDDR3 12x12 Validation Board";
+ compatible = "fsl,imx7d-12x12-lpddr3-val", "fsl,imx7d";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000 0>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+ pinctrl-1 = <&pinctrl_gpio_keys_sleep>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx7d-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_aud_1v8: aud_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can1_3v3: can1-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "can1-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 10 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_can2_3v3: can2-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "can2-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 11 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_coedc_5v: coedc_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "CODEC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_sd1_vmmc: sd1_vmmc{
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_SD1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc{
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_SD2";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio5 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg1_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_vref_1v8: regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_mipi_dsi_pwr_on: mipi_dsi_pwr_on {
+ compatible = "regulator-fixed";
+ regulator-name = "mipi_dsi_pwr_on";
+ gpio = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+
+ memory {
+ reg = <0x80000000 0x80000000>;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_1v8>;
+ status = "okay";
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+};
+
+&epdc {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_epdc_0>;
+ pinctrl-1 = <&pinctrl_epdc_0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
+&epxp {
+ status = "okay";
+};
+
+&ecspi1 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 19 0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_cs_1>;
+ pinctrl-1 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_cs_1>;
+ status = "disabled";
+
+ spi_flash1: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p32";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_enet1>;
+ pinctrl-1 = <&pinctrl_enet1>;
+ assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
+ <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+ assigned-clock-rates = <0>, <100000000>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy1>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@5 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <5>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&fec2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_enet2>;
+ pinctrl-1 = <&pinctrl_enet2>;
+ pinctrl-assert-gpios = <&max7322 0 GPIO_ACTIVE_HIGH>;
+ assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
+ <&clks IMX7D_ENET2_TIME_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+ assigned-clock-rates = <0>, <100000000>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "disabled";
+};
+
+&flexcan1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ pinctrl-1 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can1_3v3>;
+ status = "disabled";
+};
+
+&flexcan2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ pinctrl-1 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_3v3>;
+ status = "disabled";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ pinctrl-1 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ pmic: pfuze3000@8 {
+ compatible = "fsl,pfuze3000";
+ reg = <0x8>;
+ fsl,lpsr-mode;
+
+ regulators {
+ sw1a_reg: sw1a {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+ /* use sw1c_reg to align with pfuze100/pfuze200 */
+ sw1c_reg: sw1b {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1475000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1650000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vldo2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vccsd {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: v33 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vldo4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_i2c3_1>;
+ pinctrl-1 = <&pinctrl_i2c3_1>;
+ status = "okay";
+
+ max7322: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ max17135@48 {
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ vneg_pwrup = <1>;
+ gvee_pwrup = <2>;
+ vpos_pwrup = <10>;
+ gvdd_pwrup = <12>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <8>;
+ vneg_pwrdn = <10>;
+ gpio_pmic_pwrgood = <&gpio2 31 0>;
+ gpio_pmic_vcom_ctrl = <&gpio4 14 0>;
+ gpio_pmic_wakeup = <&gpio4 23 0>;
+ gpio_pmic_v3p3 = <&gpio4 20 0>;
+ gpio_pmic_intr = <&gpio4 18 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* Real max value: -500000 */
+ regulator-max-microvolt = <4325000>;
+ /* Real min value: -4325000 */
+ regulator-min-microvolt = <500000>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
+
+ codec: wm8958@1a {
+ compatible = "wlf,wm8958";
+ reg = <0x1a>;
+ clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>,
+ <&clks IMX7D_CLK_DUMMY>;
+ clock-names = "mclk1", "mclk2";
+
+ DBVDD1-supply = <&reg_aud_1v8>;
+ DBVDD2-supply = <&reg_aud_1v8>;
+ DBVDD3-supply = <&reg_aud_1v8>;
+ AVDD2-supply = <&reg_aud_1v8>;
+ CPVDD-supply = <&reg_aud_1v8>;
+ SPKVDD1-supply = <&reg_coedc_5v>;
+ SPKVDD2-supply = <&reg_coedc_5v>;
+ wlf,ldo1ena;
+ wlf,ldo2ena;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_sd2_vselect &pinctrl_hog_mipi>;
+ pinctrl-1 = <&pinctrl_hog_1 &pinctrl_hog_sd2_vselect &pinctrl_hog_mipi>;
+
+ imx7d-12x12-lpddr3-arm2 {
+
+ pinctrl_bt: btgrp-1 {
+ fsl,pins = <
+ MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x80000000 /* BT REG on */
+ >;
+ };
+
+ pinctrl_ecspi1_cs_1: ecspi1_cs_grp-1 {
+ fsl,pins = <
+ MX7D_PAD_ECSPI1_SS0__GPIO4_IO19 0x2
+ >;
+ };
+
+ pinctrl_ecspi1_1: ecspi1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO 0x2
+ MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x2
+ MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x2
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO10__ENET1_MDIO 0x3
+ MX7D_PAD_GPIO1_IO11__ENET1_MDC 0x3
+ MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1
+ MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1
+ MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1
+ MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1
+ MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1
+ MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1
+ MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1
+ MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1
+ MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1
+ MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1
+ MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1
+ MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC 0x1
+ MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x1
+ MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x1
+ MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2 0x1
+ MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3 0x1
+ MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x1
+ MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC 0x1
+ MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x1
+ MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x1
+ MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2 0x1
+ MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3 0x1
+ MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x1
+ >;
+ };
+
+ pinctrl_epdc_0: epdcgrp-0 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA00__EPDC_DATA0 0x2
+ MX7D_PAD_EPDC_DATA01__EPDC_DATA1 0x2
+ MX7D_PAD_EPDC_DATA02__EPDC_DATA2 0x2
+ MX7D_PAD_EPDC_DATA03__EPDC_DATA3 0x2
+ MX7D_PAD_EPDC_DATA04__EPDC_DATA4 0x2
+ MX7D_PAD_EPDC_DATA05__EPDC_DATA5 0x2
+ MX7D_PAD_EPDC_DATA06__EPDC_DATA6 0x2
+ MX7D_PAD_EPDC_DATA07__EPDC_DATA7 0x2
+ MX7D_PAD_EPDC_DATA08__EPDC_DATA8 0x2
+ MX7D_PAD_EPDC_DATA09__EPDC_DATA9 0x2
+ MX7D_PAD_EPDC_DATA10__EPDC_DATA10 0x2
+ MX7D_PAD_EPDC_DATA11__EPDC_DATA11 0x2
+ MX7D_PAD_EPDC_DATA12__EPDC_DATA12 0x2
+ MX7D_PAD_EPDC_DATA13__EPDC_DATA13 0x2
+ MX7D_PAD_EPDC_DATA14__EPDC_DATA14 0x2
+ MX7D_PAD_EPDC_DATA15__EPDC_DATA15 0x2
+ MX7D_PAD_EPDC_SDCLK__EPDC_SDCLK 0x2
+ MX7D_PAD_EPDC_SDLE__EPDC_SDLE 0x2
+ MX7D_PAD_EPDC_SDOE__EPDC_SDOE 0x2
+ MX7D_PAD_EPDC_SDSHR__EPDC_SDSHR 0x2
+ MX7D_PAD_EPDC_SDCE0__EPDC_SDCE0 0x2
+ MX7D_PAD_EPDC_SDCE1__EPDC_SDCE1 0x2
+ MX7D_PAD_EPDC_SDCE2__EPDC_SDCE2 0x2
+ MX7D_PAD_EPDC_SDCE3__EPDC_SDCE3 0x2
+ MX7D_PAD_EPDC_GDCLK__EPDC_GDCLK 0x2
+ MX7D_PAD_EPDC_GDOE__EPDC_GDOE 0x2
+ MX7D_PAD_EPDC_GDRL__EPDC_GDRL 0x2
+ MX7D_PAD_EPDC_GDSP__EPDC_GDSP 0x2
+ MX7D_PAD_EPDC_BDR0__EPDC_BDR0 0x2
+ MX7D_PAD_EPDC_BDR1__EPDC_BDR1 0x2
+ MX7D_PAD_ECSPI1_MISO__GPIO4_IO18 0x80000000 /* pwr int */
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_RX_DATA__FLEXCAN1_RX 0x59
+ MX7D_PAD_SAI1_TX_BCLK__FLEXCAN1_TX 0x59
+ MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x59 /* STBY */
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_TX_SYNC__FLEXCAN2_RX 0x59
+ MX7D_PAD_SAI1_TX_DATA__FLEXCAN2_TX 0x59
+ MX7D_PAD_GPIO1_IO11__GPIO1_IO11 0x59 /* STBY */
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x32
+ MX7D_PAD_GPIO1_IO15__GPIO1_IO15 0x32
+ >;
+ };
+
+ pinctrl_gpio_keys_sleep: gpio_keysgrp_sleep {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x14
+ MX7D_PAD_GPIO1_IO15__GPIO1_IO15 0x14
+ >;
+ };
+
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C4_SCL__GPIO4_IO14 0x80000000
+ MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31 0x80000000
+ MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20 0x80000000
+ MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x80000000
+ MX7D_PAD_ECSPI2_MISO__GPIO4_IO22 0x80000000
+ MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x80000000
+ MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59
+ MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59
+ MX7D_PAD_SD1_WP__GPIO5_IO1 0x59
+ MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x59
+ MX7D_PAD_SD2_WP__GPIO5_IO10 0x59
+ MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59
+ MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59
+ >;
+ };
+
+ pinctrl_hog_mipi: hoggrp_mipi {
+ fsl,pins = <
+ MX7D_PAD_ECSPI1_SCLK__GPIO4_IO16 0x59
+ MX7D_PAD_ECSPI1_MOSI__GPIO4_IO17 0x59
+ >;
+ };
+
+ pinctrl_hog_sd2_vselect: hoggrp_sd2vselect {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO12__SD2_VSELECT 0x59
+ >;
+ };
+
+ pinctrl_hog_headphone_det: hoggrp_headphone_det {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59
+ >;
+ };
+
+ pinctrl_i2c1_1: i2c1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f
+ MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c2_1: i2c2grp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f
+ MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c3_1: i2c3grp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C3_SDA__I2C3_SDA 0x4000007f
+ MX7D_PAD_I2C3_SCL__I2C3_SCL 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c4_1: i2c4grp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C4_SDA__I2C4_SDA 0x4000007f
+ MX7D_PAD_I2C4_SCL__I2C4_SCL 0x4000007f
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX7D_PAD_LCD_DATA00__LCD_DATA0 0x79
+ MX7D_PAD_LCD_DATA01__LCD_DATA1 0x79
+ MX7D_PAD_LCD_DATA02__LCD_DATA2 0x79
+ MX7D_PAD_LCD_DATA03__LCD_DATA3 0x79
+ MX7D_PAD_LCD_DATA04__LCD_DATA4 0x79
+ MX7D_PAD_LCD_DATA05__LCD_DATA5 0x79
+ MX7D_PAD_LCD_DATA06__LCD_DATA6 0x79
+ MX7D_PAD_LCD_DATA07__LCD_DATA7 0x79
+ MX7D_PAD_LCD_DATA08__LCD_DATA8 0x79
+ MX7D_PAD_LCD_DATA09__LCD_DATA9 0x79
+ MX7D_PAD_LCD_DATA10__LCD_DATA10 0x79
+ MX7D_PAD_LCD_DATA11__LCD_DATA11 0x79
+ MX7D_PAD_LCD_DATA12__LCD_DATA12 0x79
+ MX7D_PAD_LCD_DATA13__LCD_DATA13 0x79
+ MX7D_PAD_LCD_DATA14__LCD_DATA14 0x79
+ MX7D_PAD_LCD_DATA15__LCD_DATA15 0x79
+ MX7D_PAD_LCD_DATA16__LCD_DATA16 0x79
+ MX7D_PAD_LCD_DATA17__LCD_DATA17 0x79
+ MX7D_PAD_LCD_DATA18__LCD_DATA18 0x79
+ MX7D_PAD_LCD_DATA19__LCD_DATA19 0x79
+ MX7D_PAD_LCD_DATA20__LCD_DATA20 0x79
+ MX7D_PAD_LCD_DATA21__LCD_DATA21 0x79
+ MX7D_PAD_LCD_DATA22__LCD_DATA22 0x79
+ MX7D_PAD_LCD_DATA23__LCD_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX7D_PAD_LCD_CLK__LCD_CLK 0x79
+ MX7D_PAD_LCD_ENABLE__LCD_ENABLE 0x79
+ MX7D_PAD_LCD_VSYNC__LCD_VSYNC 0x79
+ MX7D_PAD_LCD_HSYNC__LCD_HSYNC 0x79
+ >;
+ };
+
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_RX_SYNC__MQS_RIGHT 0x0
+ MX7D_PAD_SAI1_RX_BCLK__MQS_LEFT 0x0
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX7D_PAD_SAI2_TX_SYNC__GPIO6_IO19 0x2
+ MX7D_PAD_SAI2_RX_DATA__GPIO6_IO21 0x2
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_MCLK__SAI1_MCLK 0x1f
+ MX7D_PAD_SAI1_TX_BCLK__SAI1_TX_BCLK 0x1f
+ MX7D_PAD_SAI1_TX_SYNC__SAI1_TX_SYNC 0x1f
+ MX7D_PAD_SAI1_RX_SYNC__SAI1_RX_SYNC 0x1f
+ MX7D_PAD_SAI1_RX_DATA__SAI1_RX_DATA0 0x1f
+ MX7D_PAD_SAI1_TX_DATA__SAI1_TX_DATA0 0
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX7D_PAD_SAI2_TX_BCLK__SAI2_TX_BCLK 0x1f
+ MX7D_PAD_SAI2_TX_SYNC__SAI2_TX_SYNC 0x1f
+ MX7D_PAD_SAI2_RX_DATA__SAI2_RX_DATA0 0x1f
+ MX7D_PAD_SAI2_TX_DATA__SAI2_TX_DATA0 0
+ >;
+ };
+
+ pinctrl_uart1_1: uart1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
+ MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79
+ >;
+ };
+
+ pinctrl_uart3_1: uart3grp-1 {
+ fsl,pins = <
+ MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX 0x79
+ MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX 0x79
+ MX7D_PAD_UART3_CTS_B__UART3_DCE_CTS 0x79
+ MX7D_PAD_UART3_RTS_B__UART3_DCE_RTS 0x79
+ >;
+ };
+
+ pinctrl_uart3dte_1: uart3dtegrp-1 {
+ fsl,pins = <
+ MX7D_PAD_UART3_TX_DATA__UART3_DTE_RX 0x79
+ MX7D_PAD_UART3_RX_DATA__UART3_DTE_TX 0x79
+ MX7D_PAD_UART3_RTS_B__UART3_DTE_CTS 0x79
+ MX7D_PAD_UART3_CTS_B__UART3_DTE_RTS 0x79
+ >;
+ };
+
+ pinctrl_usdhc1_1: usdhc1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SD1_CMD__SD1_CMD 0x59
+ MX7D_PAD_SD1_CLK__SD1_CLK 0x19
+ MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59
+ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59
+ MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59
+ MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59
+ >;
+ };
+
+ pinctrl_usdhc2_1: usdhc2grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x59
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x19
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59
+ >;
+ };
+
+ pinctrl_usdhc2_1_100mhz: usdhc2grp-1_100mhz {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x5a
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x1a
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5a
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5a
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5a
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5a
+ >;
+ };
+
+ pinctrl_usdhc2_1_200mhz: usdhc2grp-1_200mhz {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x5b
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x1b
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5b
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5b
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5b
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5b
+ >;
+ };
+
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SD3_CMD__SD3_CMD 0x59
+ MX7D_PAD_SD3_CLK__SD3_CLK 0x19
+ MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59
+ MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59
+ MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59
+ MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59
+ MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59
+ MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59
+ MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59
+ MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59
+ MX7D_PAD_SD3_STROBE__SD3_STROBE 0x19
+ >;
+ };
+
+ pinctrl_usdhc3_1_100mhz: usdhc3grp-1_100mhz {
+ fsl,pins = <
+ MX7D_PAD_SD3_CMD__SD3_CMD 0x5a
+ MX7D_PAD_SD3_CLK__SD3_CLK 0x1a
+ MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5a
+ MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5a
+ MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5a
+ MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5a
+ MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5a
+ MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5a
+ MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5a
+ MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5a
+ MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1a
+ >;
+ };
+
+ pinctrl_usdhc3_1_200mhz: usdhc3grp-1_200mhz {
+ fsl,pins = <
+ MX7D_PAD_SD3_CMD__SD3_CMD 0x5b
+ MX7D_PAD_SD3_CLK__SD3_CLK 0x1b
+ MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5b
+ MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5b
+ MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5b
+ MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5b
+ MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5b
+ MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5b
+ MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5b
+ MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5b
+ MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1b
+ >;
+ };
+
+ pinctrl_sim1_1: sim1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SAI1_TX_SYNC__SIM1_PORT1_RST_B 0x77
+ MX7D_PAD_SAI1_RX_SYNC__SIM1_PORT1_PD 0x77
+ MX7D_PAD_SAI1_TX_DATA__SIM1_PORT1_SVEN 0x77
+ MX7D_PAD_SAI1_TX_BCLK__SIM1_PORT1_CLK 0x73
+ MX7D_PAD_SAI1_RX_DATA__SIM1_PORT1_TRXD 0x73
+ >;
+ };
+
+ };
+};
+
+&iomuxc_lpsr {
+ imx7d-12x12-lpddr3-arm2 {
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO01__PWM1_OUT 0x30
+ >;
+ };
+ };
+
+ imx7d-sdb {
+ pinctrl_usbotg1_vbus: usbotg1vbusgrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5 0x14
+ >;
+ };
+
+ pinctrl_usbotg2_vbus: usbotg2vbusgrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO07__GPIO1_IO7 0x14
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B 0x74
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ pinctrl-1 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&ocrams {
+ fsl,enable-lpsr;
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio6 21 GPIO_ACTIVE_LOW>;
+ power-on-gpio = <&gpio6 19 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&sim1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_sim1_1>;
+ pinctrl-1 = <&pinctrl_sim1_1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ pinctrl-1 = <&pinctrl_uart1_1>;
+ assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_uart3_1
+ &pinctrl_bt>;
+ pinctrl-1 = <&pinctrl_uart3_1
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode;*/
+ /* pinctrl-0 = <&pinctrl_uart3dte_1>; */
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg2_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1_1>;
+ pinctrl-1 = <&pinctrl_usdhc1_1>;
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
+ pinctrl-3 = <&pinctrl_usdhc2_1>;
+ cd-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd2_vmmc>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+ pinctrl-3 = <&pinctrl_usdhc3_1>;
+ assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
+ assigned-clock-rates = <400000000>;
+ bus-width = <8>;
+ auto-cmd23-broken;
+ non-removable;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-epdc.dts b/arch/arm/boot/dts/imx7d-sdb-epdc.dts
new file mode 100644
index 000000000000..2d3df3dcd5f8
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-epdc.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ */
+#include "imx7d-sdb.dts"
+#include "imx7d-sdb-epdc.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-epdc.dtsi b/arch/arm/boot/dts/imx7d-sdb-epdc.dtsi
new file mode 100644
index 000000000000..8dda20b53c5a
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-epdc.dtsi
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2019 NXP
+ */
+
+&epdc {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&fec2 {
+ status = "disabled";
+};
+
+&reg_can2_3v3 {
+ status = "disabled";
+};
+
+&reg_fec2_3v3 {
+ status = "disabled";
+};
+
+&flexcan2 {
+ status = "disabled";
+};
+
+&max17135 {
+ status = "okay";
+};
+
+&sii902x {
+ status = "disabled";
+};
+
+&sim1 {
+ status = "disabled";
+};
+
+&uart5 {
+ status = "disabled";
+};
+
+&i2c3 {
+ elan@10 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc_elan_touch>;
+ compatible = "elan,elan-touch";
+ reg = <0x10>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+ gpio_elan_cs = <&gpio6 13 0>;
+ gpio_elan_rst = <&gpio6 15 0>;
+ gpio_intr = <&gpio6 12 0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dts b/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dts
new file mode 100644
index 000000000000..346e38cca609
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dts
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx7d-sdb.dts"
+#include "imx7d-sdb-gpmi-weim.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dtsi b/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dtsi
new file mode 100644
index 000000000000..a614cbf05aa8
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-gpmi-weim.dtsi
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+&gpmi{
+ status = "okay";
+};
+
+/* &sai1{ */
+ /* status = "disabled"; */
+/* }; */
+
+&usdhc3{
+ status = "disabled";
+};
+
+&uart5{
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-m4.dts b/arch/arm/boot/dts/imx7d-sdb-m4.dts
new file mode 100644
index 000000000000..7aa803559ef5
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-m4.dts
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx7d-sdb.dts"
+#include "imx7d-sdb-m4.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-m4.dtsi b/arch/arm/boot/dts/imx7d-sdb-m4.dtsi
new file mode 100644
index 000000000000..601a236f5372
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-m4.dtsi
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+/ {
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ m4_reserved: m4@0x9ff00000 {
+ no-map;
+ reg = <0x9ff00000 0x100000>;
+ };
+
+ rpmsg_reserved: rpmsg@0xbff00000 {
+ no-map;
+ reg = <0xbff00000 0x100000>;
+ };
+ };
+ m4_tcm: tcml@007f8000 {
+ compatible = "fsl, m4_tcml";
+ reg = <0x007f8000 0x8000>;
+ };
+};
+
+&adc1 {
+ status = "disabled";
+};
+
+&adc2 {
+ status = "disabled";
+};
+
+&flexcan1 {
+ status = "disabled";
+};
+
+&flexcan2 {
+ status = "disabled";
+};
+
+&i2c2 {
+ status = "disabled";
+};
+
+&gpt3 {
+ status = "disabled";
+};
+
+&gpt4 {
+ status = "disabled";
+};
+
+&ocram {
+ reg = <0x00901000 0xf000>;
+};
+
+&reg_can2_3v3 {
+ status = "disabled";
+};
+
+&rpmsg{
+ vdev-nums = <1>;
+ reg = <0xbfff0000 0x10000>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&wdog3{
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-mipi-dsi.dts b/arch/arm/boot/dts/imx7d-sdb-mipi-dsi.dts
new file mode 100644
index 000000000000..327d976e4066
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-mipi-dsi.dts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx7d-sdb.dts"
+
+/ {
+ mipi_dsi_reset: mipi-dsi-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+};
+
+&lcdif {
+ disp-dev = "mipi_dsi_samsung";
+ disp-videomode = "TRUULY-WVGA-SYNC-LOW";
+};
+
+&mipi_dsi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
+ lcd_panel = "TRULY-WVGA-TFT3P5581E";
+ resets = <&mipi_dsi_reset>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-qspi.dts b/arch/arm/boot/dts/imx7d-sdb-qspi.dts
new file mode 100644
index 000000000000..a46990554d28
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-qspi.dts
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 "imx7d-sdb.dts"
+#include "imx7d-sdb-qspi.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-qspi.dtsi b/arch/arm/boot/dts/imx7d-sdb-qspi.dtsi
new file mode 100644
index 000000000000..513c597ff078
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-qspi.dtsi
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+/* disable epdc, conflict with qspi */
+&epdc {
+ status = "disabled";
+};
+
+&iomuxc {
+ qspi1 {
+ pinctrl_qspi1_1: qspi1grp_1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA00__QSPI_A_DATA0 0x51
+ MX7D_PAD_EPDC_DATA01__QSPI_A_DATA1 0x51
+ MX7D_PAD_EPDC_DATA02__QSPI_A_DATA2 0x51
+ MX7D_PAD_EPDC_DATA03__QSPI_A_DATA3 0x51
+ MX7D_PAD_EPDC_DATA05__QSPI_A_SCLK 0x51
+ MX7D_PAD_EPDC_DATA06__QSPI_A_SS0_B 0x51
+ >;
+ };
+ };
+};
+
+&qspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi1_1>;
+ status = "okay";
+ ddrsmp=<0>;
+
+ flash0: mx25l51245g@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ reg = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-usd-wifi.dts b/arch/arm/boot/dts/imx7d-sdb-usd-wifi.dts
new file mode 100644
index 000000000000..9c0642fdff41
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-usd-wifi.dts
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2020 NXP
+ */
+
+#include "imx7d-sdb.dts"
+
+/ {
+ reg_sd2_vmmc: regulator-sd2-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_SD2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_brcm_reg>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+};
+
+&reg_sd1_vmmc {
+ regulator-always-on;
+};
+
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>;
+ /delete-property/ cd-gpios;
+ /delete-property/ wp-gpios;
+ no-1-8-v;
+ pm-ignore-notify;
+ keep-power-in-suspend;
+ non-removable;
+ cap-power-off-card;
+
+ brcmf2: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+&usdhc2 {
+ status = "disabled";
+};
+
+&usdhc2_pwrseq {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 869efbc4af42..096cc16697b7 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -19,6 +19,26 @@
reg = <0x80000000 0x80000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -56,6 +76,7 @@
#gpio-cells = <2>;
reg = <0>;
registers-number = <1>;
+ registers-default = /bits/ 8 <0x74>; /* Enable PERI_3V3, SENSOR_RST_B and HDMI_RST*/
spi-max-frequency = <100000>;
};
};
@@ -87,16 +108,15 @@
regulator-max-microvolt = <1800000>;
};
- reg_brcm: regulator-brcm {
+ reg_sd1_vmmc: regulator-sd1-vmmc {
compatible = "regulator-fixed";
- gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- regulator-name = "brcm_reg";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_brcm_reg>;
+ regulator-name = "VDD_SD1";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
startup-delay-us = <200000>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
};
reg_lcd_3v3: regulator-lcd-3v3 {
@@ -135,16 +155,48 @@
status = "okay";
};
- panel {
- compatible = "innolux,at043tn24";
- backlight = <&backlight>;
- power-supply = <&reg_lcd_3v3>;
+ pxp_v4l2_out {
+ compatible = "fsl,imx7d-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
- port {
- panel_in: endpoint {
- remote-endpoint = <&display_out>;
- };
- };
+ sound {
+ compatible = "fsl,imx7d-evk-wm8960", "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ cpu-dai = <&sai1>;
+ audio-codec = <&codec>;
+ codec-master;
+ /* JD2: hp detect high for headphone*/
+ hp-det = <2 0>;
+ hp-det-gpios = <&gpio2 28 0>;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Main MIC",
+ "Main MIC", "MICB";
+ assigned-clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_SRC>,
+ <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <0>, <12288000>;
+ };
+
+ sound-hdmi {
+ compatible = "fsl,imx7d-sdb-sii902x",
+ "fsl,imx-audio-sii902x";
+ model = "sii902x-audio";
+ cpu-dai = <&sai3>;
+ hdmi-controller = <&sii902x>;
+ };
+
+ usdhc2_pwrseq: usdhc2_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_brcm_reg>;
+ reset-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>;
};
};
@@ -162,6 +214,23 @@
cpu-supply = <&sw1a_reg>;
};
+&clks {
+ assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <884736000>;
+};
+
+&csi1 {
+ csi-mux-mipi = <&gpr 0x14 4>;
+ fsl,mipi-mode;
+ status = "okay";
+
+ port {
+ csi_ep: endpoint {
+ remote-endpoint = <&csi_mipi_ep>;
+ };
+ };
+};
+
&ecspi3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi3>;
@@ -187,13 +256,32 @@
};
};
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0 &pinctrl_enet2_reg>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ en-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+};
+
+&epxp {
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
- assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
- <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
- assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
- assigned-clock-rates = <0>, <100000000>;
+ assigned-clocks = <&clks IMX7D_ENET_PHY_REF_ROOT_SRC>,
+ <&clks IMX7D_ENET_AXI_ROOT_SRC>,
+ <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
+ <&clks IMX7D_ENET1_TIME_ROOT_CLK>,
+ <&clks IMX7D_ENET_AXI_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_25M_CLK>,
+ <&clks IMX7D_PLL_ENET_MAIN_250M_CLK>,
+ <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+ assigned-clock-rates = <0>, <0>, <0>, <100000000>, <250000000>;
phy-mode = "rgmii";
phy-handle = <&ethphy0>;
fsl,magic-packet;
@@ -217,10 +305,15 @@
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
- assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
- <&clks IMX7D_ENET2_TIME_ROOT_CLK>;
- assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
- assigned-clock-rates = <0>, <100000000>;
+ assigned-clocks = <&clks IMX7D_ENET_PHY_REF_ROOT_SRC>,
+ <&clks IMX7D_ENET_AXI_ROOT_SRC>,
+ <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
+ <&clks IMX7D_ENET2_TIME_ROOT_CLK>,
+ <&clks IMX7D_ENET_AXI_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_25M_CLK>,
+ <&clks IMX7D_PLL_ENET_MAIN_250M_CLK>,
+ <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+ assigned-clock-rates = <0>, <0>, <0>, <100000000>, <250000000>;
phy-mode = "rgmii";
phy-handle = <&ethphy1>;
phy-supply = <&reg_fec2_3v3>;
@@ -235,6 +328,31 @@
status = "okay";
};
+&mipi_csi {
+ clock-frequency = <240000000>;
+ status = "okay";
+ port {
+ mipi_sensor_ep: endpoint@1 {
+ remote-endpoint = <&ov5640_mipi_ep>;
+ data-lanes = <2>;
+ csis-hs-settle = <13>;
+ csis-clk-settle = <2>;
+ csis-wclk;
+ };
+
+ csi_mipi_ep: endpoint@2 {
+ remote-endpoint = <&csi_ep>;
+ };
+ };
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
@@ -336,6 +454,16 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ fxas2100x@20 {
+ compatible = "fsl,fxas2100x";
+ reg = <0x20>;
+ };
+
+ fxos8700@1e {
+ compatible = "fsl,fxos8700";
+ reg = <0x1e>;
+ };
+
mpl3115@60 {
compatible = "fsl,mpl3115";
reg = <0x60>;
@@ -346,6 +474,88 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
+
+ sii902x: sii902x@39 {
+ compatible = "SiI,sii902x";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sii902x>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+ mode_str ="1280x720M@60";
+ bits-per-pixel = <16>;
+ reg = <0x39>;
+ status = "okay";
+ };
+
+ max17135: max17135@48 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_max17135>;
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ status = "disabled";
+
+ vneg_pwrup = <1>;
+ gvee_pwrup = <2>;
+ vpos_pwrup = <10>;
+ gvdd_pwrup = <12>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <8>;
+ vneg_pwrdn = <10>;
+ gpio_pmic_pwrgood = <&gpio2 31 0>;
+ gpio_pmic_vcom_ctrl = <&gpio4 14 0>;
+ gpio_pmic_wakeup = <&gpio2 23 0>;
+ gpio_pmic_v3p3 = <&gpio2 30 0>;
+ gpio_pmic_intr = <&gpio2 22 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* Real max value: -500000 */
+ regulator-max-microvolt = <4325000>;
+ /* Real min value: -4325000 */
+ regulator-min-microvolt = <500000>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
};
&i2c4 {
@@ -360,16 +570,54 @@
clock-names = "mclk";
wlf,shared-lrclk;
};
+
+ ov5640_mipi: ov5640_mipi@3c {
+ compatible = "ovti,ov5640_mipi";
+ reg = <0x3c>;
+ clocks = <&clks IMX7D_CLK_DUMMY>;
+ clock-names = "csi_mclk";
+ csi_id = <0>;
+ pwn-gpios = <&extended_io 6 GPIO_ACTIVE_HIGH>;
+ AVDD-supply = <&vgen6_reg>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ port {
+ ov5640_mipi_ep: endpoint {
+ remote-endpoint = <&mipi_sensor_ep>;
+ };
+ };
+ };
};
&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif>;
+ lcd-supply = <&reg_lcd_3v3>;
+ display = <&display0>;
status = "okay";
- port {
- display_out: endpoint {
- remote-endpoint = <&panel_in>;
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
};
};
};
@@ -387,6 +635,38 @@
vin-supply = <&sw2_reg>;
};
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ assigned-clocks = <&clks IMX7D_SAI1_ROOT_SRC>,
+ <&clks IMX7D_SAI1_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <0>, <36864000>;
+ status = "okay";
+};
+
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3 &pinctrl_sai3_mclk>;
+ assigned-clocks = <&clks IMX7D_SAI3_ROOT_SRC>,
+ <&clks IMX7D_SAI3_ROOT_CLK>;
+ assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <0>, <36864000>;
+ status = "okay";
+};
+
+&sim1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sim1_1>;
+ port = <0>;
+ sven_low_active;
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
&snvs_pwrkey {
status = "okay";
};
@@ -395,7 +675,18 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ assigned-clocks = <&clks IMX7D_UART5_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart5dte>; */
status = "okay";
};
@@ -405,6 +696,7 @@
assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
uart-has-rtscts;
+ resets = <&modem_reset>;
status = "okay";
};
@@ -420,26 +712,35 @@
};
&usdhc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_gpio>;
cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
- wakeup-source;
- keep-power-in-suspend;
+ vmmc-supply = <&reg_sd1_vmmc>;
status = "okay";
};
&usdhc2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
pinctrl-names = "default", "state_100mhz", "state_200mhz";
- pinctrl-0 = <&pinctrl_usdhc2>;
- pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
- pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
- wakeup-source;
+ pinctrl-0 = <&pinctrl_usdhc2 &pinctrl_wifi>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz &pinctrl_wifi>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz &pinctrl_wifi>;
keep-power-in-suspend;
non-removable;
- vmmc-supply = <&reg_brcm>;
+ mmc-pwrseq = <&usdhc2_pwrseq>;
fsl,tuning-step = <2>;
+ pm-ignore-notify;
+ cap-power-off-card;
status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
};
&usdhc3 {
@@ -450,8 +751,8 @@
assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
assigned-clock-rates = <400000000>;
bus-width = <8>;
- fsl,tuning-step = <2>;
non-removable;
+ auto-cmd23-broken;
status = "okay";
};
@@ -472,6 +773,19 @@
>;
};
+ pinctrl_epdc_elan_touch: epdc_elan_touch_grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_RX_DATA__GPIO6_IO12 0x59
+ MX7D_PAD_SAI1_TX_DATA__GPIO6_IO15 0x1b
+ MX7D_PAD_SAI1_TX_BCLK__GPIO6_IO13 0x80000000
+ >;
+ };
+ pinctrl_mipi_dsi_reset: mipi_dsi_reset_grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_TX_DATA__GPIO6_IO15 0x1b
+ >;
+ };
+
pinctrl_ecspi3: ecspi3grp {
fsl,pins = <
MX7D_PAD_SAI2_TX_SYNC__ECSPI3_MISO 0x2
@@ -517,9 +831,34 @@
>;
};
- pinctrl_enet2_reg: enet2reggrp {
+ pinctrl_epdc0: epdcgrp0 {
fsl,pins = <
- MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x14
+ MX7D_PAD_EPDC_DATA00__EPDC_DATA0 0x2
+ MX7D_PAD_EPDC_DATA01__EPDC_DATA1 0x2
+ MX7D_PAD_EPDC_DATA02__EPDC_DATA2 0x2
+ MX7D_PAD_EPDC_DATA03__EPDC_DATA3 0x2
+ MX7D_PAD_EPDC_DATA04__EPDC_DATA4 0x2
+ MX7D_PAD_EPDC_DATA05__EPDC_DATA5 0x2
+ MX7D_PAD_EPDC_DATA06__EPDC_DATA6 0x2
+ MX7D_PAD_EPDC_DATA07__EPDC_DATA7 0x2
+ MX7D_PAD_EPDC_DATA08__EPDC_DATA8 0x2
+ MX7D_PAD_EPDC_DATA09__EPDC_DATA9 0x2
+ MX7D_PAD_EPDC_DATA10__EPDC_DATA10 0x2
+ MX7D_PAD_EPDC_DATA11__EPDC_DATA11 0x2
+ MX7D_PAD_EPDC_DATA12__EPDC_DATA12 0x2
+ MX7D_PAD_EPDC_DATA13__EPDC_DATA13 0x2
+ MX7D_PAD_EPDC_DATA14__EPDC_DATA14 0x2
+ MX7D_PAD_EPDC_DATA15__EPDC_DATA15 0x2
+ MX7D_PAD_EPDC_SDCLK__EPDC_SDCLK 0x2
+ MX7D_PAD_EPDC_SDLE__EPDC_SDLE 0x2
+ MX7D_PAD_EPDC_SDOE__EPDC_SDOE 0x2
+ MX7D_PAD_EPDC_SDSHR__EPDC_SDSHR 0x2
+ MX7D_PAD_EPDC_SDCE0__EPDC_SDCE0 0x2
+ MX7D_PAD_EPDC_SDCE1__EPDC_SDCE1 0x2
+ MX7D_PAD_EPDC_GDCLK__EPDC_GDCLK 0x2
+ MX7D_PAD_EPDC_GDOE__EPDC_GDOE 0x2
+ MX7D_PAD_EPDC_GDRL__EPDC_GDRL 0x2
+ MX7D_PAD_EPDC_GDSP__EPDC_GDSP 0x2
>;
};
@@ -543,6 +882,27 @@
>;
};
+ pinctrl_gpmi_nand_1: gpmi-nand-1 {
+ fsl,pins = <
+ MX7D_PAD_SD3_CLK__NAND_CLE 0x71
+ MX7D_PAD_SD3_CMD__NAND_ALE 0x71
+ MX7D_PAD_SAI1_MCLK__NAND_WP_B 0x71
+ MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71
+ MX7D_PAD_SAI1_RX_DATA__NAND_CE1_B 0x71
+ MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74
+ MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71
+ MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71
+ MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71
+ MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71
+ MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71
+ MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71
+ MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71
+ MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71
+ MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71
+ MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71
+ >;
+ };
+
pinctrl_hog: hoggrp {
fsl,pins = <
MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */
@@ -611,6 +971,43 @@
>;
};
+ pinctrl_max17135: max17135grp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31 0x80000000 /* pwrgood */
+ MX7D_PAD_I2C4_SCL__GPIO4_IO14 0x80000000 /* vcom_ctrl */
+ MX7D_PAD_EPDC_SDCE3__GPIO2_IO23 0x80000000 /* wakeup */
+ MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 0x80000000 /* v3p3 */
+ MX7D_PAD_EPDC_SDCE2__GPIO2_IO22 0x80000000 /* pwr int */
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_MCLK__SAI1_MCLK 0x1f
+ MX7D_PAD_ENET1_RX_CLK__SAI1_TX_BCLK 0x1f
+ MX7D_PAD_ENET1_CRS__SAI1_TX_SYNC 0x1f
+ MX7D_PAD_ENET1_COL__SAI1_TX_DATA0 0x30
+ MX7D_PAD_ENET1_TX_CLK__SAI1_RX_DATA0 0x1f
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX7D_PAD_SAI2_TX_BCLK__SAI2_TX_BCLK 0x1f
+ MX7D_PAD_SAI2_TX_SYNC__SAI2_TX_SYNC 0x1f
+ MX7D_PAD_SAI2_TX_DATA__SAI2_TX_DATA0 0x30
+ MX7D_PAD_SAI2_RX_DATA__SAI2_RX_DATA0 0x1f
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX7D_PAD_UART3_TX_DATA__SAI3_TX_BCLK 0x1f
+ MX7D_PAD_UART3_CTS_B__SAI3_TX_SYNC 0x1f
+ MX7D_PAD_UART3_RTS_B__SAI3_TX_DATA0 0x30
+ >;
+ };
+
pinctrl_spi4: spi4grp {
fsl,pins = <
MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59
@@ -625,6 +1022,22 @@
>;
};
+ pinctrl_sii902x: hdmigrp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x59
+ >;
+ };
+
+ pinctrl_sim1_1: sim1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA10__SIM1_PORT1_RST_B 0x77
+ MX7D_PAD_EPDC_DATA12__SIM1_PORT1_PD 0x77
+ MX7D_PAD_EPDC_DATA11__SIM1_PORT1_SVEN 0x77
+ MX7D_PAD_EPDC_DATA09__SIM1_PORT1_CLK 0x73
+ MX7D_PAD_EPDC_DATA08__SIM1_PORT1_TRXD 0x73
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
@@ -636,8 +1049,13 @@
fsl,pins = <
MX7D_PAD_SAI1_TX_BCLK__UART5_DCE_TX 0x79
MX7D_PAD_SAI1_RX_DATA__UART5_DCE_RX 0x79
- MX7D_PAD_SAI1_TX_SYNC__UART5_DCE_CTS 0x79
- MX7D_PAD_SAI1_TX_DATA__UART5_DCE_RTS 0x79
+ >;
+ };
+
+ pinctrl_uart5dte: uart5dtegrp {
+ fsl,pins = <
+ MX7D_PAD_SAI1_TX_BCLK__UART5_DTE_RX 0x79
+ MX7D_PAD_SAI1_RX_DATA__UART5_DTE_TX 0x79
>;
};
@@ -650,6 +1068,15 @@
>;
};
+ pinctrl_usdhc1_gpio: usdhc1_gpiogrp {
+ fsl,pins = <
+ MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */
+ MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */
+ MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */
+ MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x59 /* VSELECT */
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX7D_PAD_SD1_CMD__SD1_CMD 0x59
@@ -658,9 +1085,28 @@
MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59
MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59
MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59
- MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */
- MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */
- MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */
+ >;
+ };
+
+ 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
>;
};
@@ -745,6 +1191,12 @@
MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1b
>;
};
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20 0x19 /* WL_HOST_WAKE */
+ >;
+ };
};
};
@@ -755,6 +1207,12 @@
};
&iomuxc_lpsr {
+ pinctrl_enet2_reg: enet2reggrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x80000000
+ >;
+ };
+
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B 0x74
@@ -772,4 +1230,11 @@
MX7D_PAD_LPSR_GPIO1_IO07__GPIO1_IO7 0x14
>;
};
+
+ pinctrl_sai3_mclk: sai3grp_mclk {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO03__SAI3_MCLK 0x1f
+ >;
+ };
+
};
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index 9c8dd32cc035..b620366fb01c 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -22,7 +22,6 @@
reg = <1>;
clock-frequency = <996000000>;
operating-points-v2 = <&cpu0_opp_table>;
- cpu-idle-states = <&cpu_sleep_wait>;
};
};
@@ -69,6 +68,56 @@
};
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>;
@@ -106,15 +155,157 @@
};
};
+/delete-node/&csi;
+/delete-node/&video_mux;
+
&aips2 {
pcie_phy: pcie-phy@306d0000 {
compatible = "fsl,imx7d-pcie-phy";
reg = <0x306d0000 0x10000>;
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>;
+ reg = <0x306f0000 0x10000>;
+ clocks = <&clks IMX7D_CLK_DUMMY>, <&clks IMX7D_EPDC_PIXEL_ROOT_CLK>;
+ clock-names = "epdc_axi", "epdc_pix";
+ epdc-ram = <&gpr 0x4 30>;
+ qos = <&qosc>;
+ 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>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_MIPI_CSI_ROOT_CLK>,
+ <&clks IMX7D_MIPI_DPHY_ROOT_CLK>;
+ clock-names = "mipi_clk", "phy_clk";
+ mipi-phy-supply = <&reg_1p0d>;
+ csis-phy-reset = <&src 0x28 2>;
+ bus-width = <4>;
+ status = "disabled";
+ /delete-node/ port@0;
+ /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>;
+ };
};
&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>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_MU_ROOT_CLK>;
+ clock-names = "mu";
+ 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>;
+ compatible = "fsl,imx7d-qspi";
+ reg = <0x30bb0000 0x10000>, <0x60000000 0x10000000>;
+ reg-names = "QuadSPI", "QuadSPI-memory";
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_QSPI_ROOT_CLK>,
+ <&clks IMX7D_QSPI_ROOT_CLK>;
+ clock-names = "qspi_en", "qspi";
+ 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>;
@@ -144,7 +335,7 @@
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,
- <&clks IMX7D_ENET_PHY_REF_ROOT_CLK>;
+ <&clks IMX7D_ENET_PHY_REF_ROOT_DIV>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
@@ -195,6 +386,20 @@
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.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index e2e604d6ba0b..0f428e36dac8 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -53,19 +53,6 @@
#address-cells = <1>;
#size-cells = <0>;
- idle-states {
- entry-method = "psci";
-
- cpu_sleep_wait: cpu-sleep-wait {
- compatible = "arm,idle-state";
- arm,psci-suspend-param = <0x0010000>;
- local-timer-stop;
- entry-latency-us = <100>;
- exit-latency-us = <50>;
- min-residency-us = <1000>;
- };
- };
-
cpu0: cpu@0 {
compatible = "arm,cortex-a7";
device_type = "cpu";
@@ -73,7 +60,6 @@
clock-frequency = <792000000>;
clock-latency = <61036>; /* two CLK32 periods */
clocks = <&clks IMX7D_CLK_ARM>;
- cpu-idle-states = <&cpu_sleep_wait>;
};
};
@@ -158,15 +144,6 @@
clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>;
};
- timer {
- compatible = "arm,armv7-timer";
- interrupt-parent = <&intc>;
- interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
- };
-
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -216,6 +193,11 @@
};
};
+ caam_sm: caam-sm@100000 {
+ compatible = "fsl,imx7d-caam-sm", "fsl,imx6q-caam-sm";
+ reg = <0x100000 0x8000>;
+ };
+
funnel@30083000 {
compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x30083000 0x1000>;
@@ -316,6 +298,17 @@
<0x31006000 0x2000>;
};
+ timer {
+ compatible = "arm,armv7-timer";
+ arm,cpu-registers-not-fw-configured;
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <8000000>;
+ };
+
aips1: aips-bus@30000000 {
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
@@ -449,8 +442,9 @@
reg = <0x302d0000 0x10000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
- <&clks IMX7D_GPT1_ROOT_CLK>;
- clock-names = "ipg", "per";
+ <&clks IMX7D_GPT1_ROOT_CLK>,
+ <&clks IMX7D_GPT_3M_CLK>;
+ clock-names = "ipg", "per", "osc_per";
};
gpt2: gpt@302e0000 {
@@ -593,6 +587,20 @@
};
};
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
+ caam_snvs: caam-snvs@30370000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x30370000 0x10000>;
+ };
+
snvs: snvs@30370000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x30370000 0x10000>;
@@ -607,10 +615,21 @@
clock-names = "snvs-rtc";
};
+ snvs_poweroff: snvs-poweroff {
+ compatible = "syscon-poweroff";
+ regmap = <&snvs>;
+ offset = <0x38>;
+ value = <0x60>;
+ mask = <0x60>;
+ status = "disabled";
+ };
+
snvs_pwrkey: snvs-powerkey {
compatible = "fsl,sec-v4.0-pwrkey";
regmap = <&snvs>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_SNVS_CLK>;
+ clock-names = "snvs";
linux,keycode = <KEY_POWER>;
wakeup-source;
status = "disabled";
@@ -628,7 +647,7 @@
};
src: src@30390000 {
- compatible = "fsl,imx7d-src", "syscon";
+ compatible = "fsl,imx7d-src", "fsl,imx51-src", "syscon";
reg = <0x30390000 0x10000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
@@ -641,6 +660,7 @@
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <3>;
interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x54010000 0xc00 0x0 0x1040640>;
#power-domain-cells = <1>;
pgc {
@@ -658,6 +678,12 @@
reg = <1>;
power-supply = <&reg_1p0d>;
};
+
+ pgc_hsic_phy: power-domain@2 {
+ #power-domain-cells = <0>;
+ reg = <2>;
+ power-supply = <&reg_1p2>;
+ };
};
};
};
@@ -767,8 +793,9 @@
reg = <0x30730000 0x10000>;
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>,
- <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>;
- clock-names = "pix", "axi";
+ <&clks IMX7D_CLK_DUMMY>,
+ <&clks IMX7D_CLK_DUMMY>;
+ clock-names = "pix", "axi", "disp_axi";
status = "disabled";
};
@@ -800,6 +827,11 @@
};
};
};
+
+ ddrc: ddrc@307a0000 {
+ compatible = "fsl,imx7-ddrc";
+ reg = <0x307a0000 0x10000>;
+ };
};
aips3: aips-bus@30800000 {
@@ -871,6 +903,8 @@
clocks = <&clks IMX7D_UART2_ROOT_CLK>,
<&clks IMX7D_UART2_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 24 4 0>, <&sdma 25 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -882,6 +916,8 @@
clocks = <&clks IMX7D_UART3_ROOT_CLK>,
<&clks IMX7D_UART3_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 26 4 0>, <&sdma 27 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1031,6 +1067,8 @@
clocks = <&clks IMX7D_UART4_ROOT_CLK>,
<&clks IMX7D_UART4_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 28 4 0>, <&sdma 29 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1042,6 +1080,8 @@
clocks = <&clks IMX7D_UART5_ROOT_CLK>,
<&clks IMX7D_UART5_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 30 4 0>, <&sdma 31 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1053,6 +1093,8 @@
clocks = <&clks IMX7D_UART6_ROOT_CLK>,
<&clks IMX7D_UART6_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 32 4 0>, <&sdma 33 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1064,6 +1106,8 @@
clocks = <&clks IMX7D_UART7_ROOT_CLK>,
<&clks IMX7D_UART7_ROOT_CLK>;
clock-names = "ipg", "per";
+ dmas = <&sdma 34 4 0>, <&sdma 35 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1101,6 +1145,7 @@
compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
reg = <0x30b30000 0x200>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pgc_hsic_phy>;
clocks = <&clks IMX7D_USB_CTRL_CLK>;
fsl,usbphy = <&usbphynop3>;
fsl,usbmisc = <&usbmisc3 0>;
@@ -1131,6 +1176,8 @@
<&clks IMX7D_USDHC1_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
status = "disabled";
};
@@ -1143,6 +1190,8 @@
<&clks IMX7D_USDHC2_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
status = "disabled";
};
@@ -1155,6 +1204,8 @@
<&clks IMX7D_USDHC3_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
status = "disabled";
};
@@ -1181,7 +1232,7 @@
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,
- <&clks IMX7D_ENET_PHY_REF_ROOT_CLK>;
+ <&clks IMX7D_ENET_PHY_REF_ROOT_DIV>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
diff --git a/arch/arm/boot/dts/imx7ulp-evk-ft5416.dts b/arch/arm/boot/dts/imx7ulp-evk-ft5416.dts
new file mode 100644
index 000000000000..b959c6852f9a
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-ft5416.dts
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx7ulp-evk.dts"
+&lpi2c7 {
+ focaltech@38 {
+ focaltech,panel-type = <FT5416>;
+ focaltech,swap-xy;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-mipi.dts b/arch/arm/boot/dts/imx7ulp-evk-mipi.dts
new file mode 100644
index 000000000000..a467fad79846
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-mipi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2017-2018 NXP.
+ *
+ * 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 "imx7ulp-evk.dts"
+#include "imx7ulp-evk-mipi.dtsi"
diff --git a/arch/arm/boot/dts/imx7ulp-evk-mipi.dtsi b/arch/arm/boot/dts/imx7ulp-evk-mipi.dtsi
new file mode 100644
index 000000000000..4caeefbf3b68
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-mipi.dtsi
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 NXP.
+ *
+ * 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.
+ */
+
+&adv7535 {
+ status = "disabled";
+
+ /delete-node/ port;
+};
+
+&mipi_dsi {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
+ pinctrl-1 = <&pinctrl_mipi_dsi_reset>;
+ lcd_panel = "TRULY-WVGA-TFT3P5581E";
+ resets = <&mipi_dsi_reset>;
+
+ /delete-node/ port;
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk.dts b/arch/arm/boot/dts/imx7ulp-evk.dts
index 4245b33bb451..c62c6222cca7 100644
--- a/arch/arm/boot/dts/imx7ulp-evk.dts
+++ b/arch/arm/boot/dts/imx7ulp-evk.dts
@@ -8,11 +8,17 @@
/dts-v1/;
#include "imx7ulp.dtsi"
+#include <dt-bindings/input/input.h>
/ {
model = "NXP i.MX7ULP EVK";
compatible = "fsl,imx7ulp-evk", "fsl,imx7ulp";
+ aliases {
+ gpio4 = &rpmsg_gpio0;
+ gpio5 = &rpmsg_gpio1;
+ };
+
chosen {
stdout-path = &lpuart4;
};
@@ -22,6 +28,38 @@
reg = <0x60000000 0x40000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ vdev0vring0: vdev0vring0@9ff00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x9ff00000 0x8000>;
+ no-map;
+ };
+ vdev0vring1: vdev0vring1@9ff08000 {
+ compatible = "shared-dma-pool";
+ reg = <0x9ff08000 0x8000>;
+ no-map;
+ };
+ vdev1vring0: vdev1vring0@9ff10000 {
+ compatible = "shared-dma-pool";
+ reg = <0x9ff10000 0x8000>;
+ no-map;
+ };
+ vdev1vring1: vdev1vring1@9ff18000 {
+ compatible = "shared-dma-pool";
+ reg = <0x9ff18000 0x8000>;
+ no-map;
+ };
+ vdev1vring3 {
+ compatible = "shared-dma-pool";
+ reg = <0x9ff20000 0xe0000>;
+ no-map;
+ };
+ };
+
backlight {
compatible = "pwm-backlight";
pwms = <&tpm4 1 50000 0>;
@@ -30,35 +68,365 @@
status = "okay";
};
- reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usbotg1_vbus>;
- regulator-name = "usb_otg1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio_ptc 0 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
-
- reg_vsd_3v3: regulator-vsd-3v3 {
- compatible = "regulator-fixed";
- regulator-name = "VSD_3V3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
+ mipi_dsi_reset: mipi-dsi-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio_ptc 19 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&rpmsg_gpio0 15 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ pf1550-rpmsg {
+ compatible = "fsl,pf1550-rpmsg";
+ sw1_reg: SW1 {
+ regulator-name = "SW1";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1387500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw2_reg: SW2 {
+ regulator-name = "SW2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1387500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3_reg: SW3 {
+ regulator-name = "SW3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: VREFDDR {
+ regulator-name = "VREFDDR";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vldo1_reg: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vldo2_reg: LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vldo3_reg: LDO3 {
+ regulator-name = "LDO3";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cell = <1>;
+ #size-cells = <0>;
+
+ reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usbotg1_vbus>;
+ pinctrl-1 = <&pinctrl_usbotg1_vbus>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio_ptc 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_vsd_3v3: regulator-vsd-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc0_rst>;
+ gpio = <&gpio_ptd 0 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd1_vmmc: sd1_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "WLAN_EN";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&rpmsg_gpio0 14 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
+ };
+ };
+
+ rpmsg_gpio0: rpmsg-gpio0 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupt-parent = <&rpmsg_gpio0>;
+ status = "okay";
+ };
+
+ rpmsg_gpio1: rpmsg-gpio1 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupt-parent = <&rpmsg_gpio1>;
+ status = "okay";
+ };
+
+ rpmsg_keys: rpmsg-keys {
+ compatible = "fsl,rpmsg-keys";
+
+ volume-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ power-on {
+ label = "PowerOn";
+ linux,code = <KEY_POWER>;
+ rpmsg-key,wakeup;
+ };
+ };
+
+ rpmsg_sensor: rpmsg-sensor {
+ compatible = "fsl,rpmsg-input";
+ };
+
+ rpmsg_i2s: rpmsg-i2s {
+ compatible = "fsl,imx7ulp-rpmsg-i2s";
+ /* the audio device index in m4 domain */
+ fsl,audioindex = <0> ;
+ status = "okay";
+ };
+
+ sound-rpmsg {
+ compatible = "fsl,imx-audio-rpmsg";
+ model = "wm8960-audio";
+ cpu-dai = <&rpmsg_i2s>;
+ rpmsg-out;
+ rpmsg-in;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT2", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Main MIC",
+ "RINPUT2", "Main MIC",
+ "Mic Jack", "MICB",
+ "Main MIC", "MICB",
+ "Playback", "CPU-Playback",
+ "CPU-Capture", "Capture";
+ };
+
+ imx7ulp-cm4 {
+ compatible = "fsl,imx7ulp-cm4";
+ ipc-only;
+ rsc-da=<0x1fff8000>;
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&mu 0 1
+ &mu 1 1
+ &mu 3 1>;
+ memory-region = <&vdev0vring0>, <&vdev0vring1>,
+ <&vdev1vring0>, <&vdev1vring1>;
+ };
+};
+
+&cpu0 {
+ arm-supply= <&sw1_reg>;
+};
+
+&lpspi3 {
+ fsl,spi-num-chipselects = <1>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpspi3>;
+ pinctrl-1 = <&pinctrl_lpspi3>;
+ status = "okay";
+
+ spidev0: spi@0 {
+ reg = <0>;
+ compatible = "rohm,dh2228fv";
+ spi-max-frequency = <1000000>;
+ };
+};
+
+&lpi2c5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpi2c5>;
+ pinctrl-1 = <&pinctrl_lpi2c5>;
+ status = "okay";
+
+ adv7535: adv7535@3d {
+ compatible = "adi,adv7535";
+ reg = <0x3d>; /* PD pin is low */
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc0_rst>;
- gpio = <&gpio_ptd 0 GPIO_ACTIVE_HIGH>;
- enable-active-high;
+ pinctrl-0 = <&pinctrl_dsi_hdmi>;
+ interrupt-parent = <&gpio_ptc>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ video-mode = <1>; /*
+ * Only support CEA modes.
+ * Reference mxc_edid.c
+ */
+ dsi-traffic-mode = <0>;
+ bpp = <24>;
+ status = "disabled";
+ };
+};
+
+&lcdif {
+ status = "okay";
+ disp-dev = "mipi_dsi_northwest";
+ display = <&display0>;
+
+ display0: display@0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <9200000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vback-porch = <2>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
};
};
&lpuart4 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_lpuart4>;
+ pinctrl-1 = <&pinctrl_lpuart4>;
+ status = "okay";
+};
+
+&lpuart6 { /* BT */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpuart6>;
+ pinctrl-1 = <&pinctrl_lpuart6>;
+ resets = <&modem_reset>;
status = "okay";
};
+&lpuart7 { /* Uart test */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpuart7>;
+ pinctrl-1 = <&pinctrl_lpuart7>;
+ status = "disabled";
+};
+
+&lpi2c7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpi2c7 &pinctrl_touch_io>;
+ pinctrl-1 = <&pinctrl_lpi2c7 &pinctrl_touch_io>;
+ status = "okay";
+
+ focaltech@38 {
+ compatible = "focaltech,fts";
+ reg = <0x38>;
+ interrupt-parent = <&gpio_ptf>;
+ interrupts = <0 0x2>;
+ focaltech,panel-type = <FT5426>;
+ focaltech,reset-gpio = <&gpio_ptf 1 0x1>;
+ focaltech,irq-gpio = <&gpio_ptf 0 0x2>;
+ focaltech,max-touch-number = <5>;
+ focaltech,display-coords = <0 0 480 854>;
+
+ focaltech,have-key;
+ focaltech,key-number = <3>;
+ focaltech,keys = <139 102 158>;
+ focaltech,key-y-coord = <2000>;
+ focaltech,key-x-coords = <200 600 800>;
+ };
+};
+
+&adv7535 {
+ status = "okay";
+
+ port {
+ dsi_to_hdmi: endpoint {
+ remote-endpoint = <&mipi_dsi_ep>;
+ };
+ };
+};
+
+&mipi_dsi {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
+ pinctrl-1 = <&pinctrl_mipi_dsi_reset>;
+ lcd_panel = "TRULY-WVGA-TFT3P5581E";
+ resets = <&mipi_dsi_reset>;
+ status = "okay";
+
+ port {
+ mipi_dsi_ep: endpoint {
+ remote-endpoint = <&dsi_to_hdmi>;
+ };
+ };
+};
+
+&rpmsg{
+ /*
+ * 64K for one rpmsg instance, default using 2 rpmsg instances:
+ * --0x9FF00000~0x9FF0FFFF: pmic,pm,audio,keys,gpio,sensor
+ * --0x9FF10000~0x9FF1FFFF: pingpong,virtual tty
+ */
+ vdev-nums = <2>;
+ reg = <0x9FF00000 0x20000>;
+ status = "disabled";
+};
+
&tpm4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0>;
@@ -67,24 +435,56 @@
&usbotg1 {
vbus-supply = <&reg_usb_otg1_vbus>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_usbotg1_id>;
+ pinctrl-1 = <&pinctrl_usbotg1_id>;
srp-disable;
hnp-disable;
adp-disable;
- over-current-active-low;
+ disable-over-current;
status = "okay";
};
&usdhc0 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
pinctrl-0 = <&pinctrl_usdhc0>;
+ pinctrl-1 = <&pinctrl_usdhc0>;
+ pinctrl-2 = <&pinctrl_usdhc0>;
+ pinctrl-3 = <&pinctrl_usdhc0>;
+ fsl,delay-line = <15>;
cd-gpios = <&gpio_ptc 10 GPIO_ACTIVE_LOW>;
vmmc-supply = <&reg_vsd_3v3>;
+ vqmmc-supply = <&vldo2_reg>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1>;
+ bus-width = <4>;
+ no-1-8-v;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ pm-ignore-notify;
+ keep-power-in-suspend;
+ non-removable;
status = "okay";
};
&iomuxc1 {
+ pinctrl_lpi2c5: lpi2c5grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTC4__LPI2C5_SCL 0x27
+ IMX7ULP_PAD_PTC5__LPI2C5_SDA 0x27
+ >;
+ };
+
+ pinctrl_mipi_dsi_reset: mipi_dsi_reset_grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTC19__PTC19 0x20003
+ >;
+ };
+
pinctrl_lpuart4: lpuart4grp {
fsl,pins = <
IMX7ULP_PAD_PTC3__LPUART4_RX 0x3
@@ -93,12 +493,54 @@
bias-pull-up;
};
+ pinctrl_lpuart6: lpuart6grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTE10__LPUART6_TX 0x3
+ IMX7ULP_PAD_PTE11__LPUART6_RX 0x3
+ IMX7ULP_PAD_PTE9__LPUART6_RTS_B 0x3
+ IMX7ULP_PAD_PTE8__LPUART6_CTS_B 0x3
+ IMX7ULP_PAD_PTE7__PTE7 0x20000 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_lpuart7: lpuart7grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTF14__LPUART7_TX 0x3
+ IMX7ULP_PAD_PTF15__LPUART7_RX 0x3
+ IMX7ULP_PAD_PTF13__LPUART7_RTS_B 0x3
+ IMX7ULP_PAD_PTF12__LPUART7_CTS_B 0x3
+ >;
+ };
+
+ pinctrl_lpi2c7: lpi2c7grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTF12__LPI2C7_SCL 0x27
+ IMX7ULP_PAD_PTF13__LPI2C7_SDA 0x27
+ >;
+ };
+
+ pinctrl_touch_io: touchiogrp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTF0__PTF0 0x10043
+ IMX7ULP_PAD_PTF1__PTF1 0x20043
+ >;
+ };
+
pinctrl_pwm0: pwm0grp {
fsl,pins = <
IMX7ULP_PAD_PTF2__TPM4_CH1 0x2
>;
};
+ pinctrl_lpspi3: lpspi3grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTF16__LPSPI3_SIN 0x0
+ IMX7ULP_PAD_PTF17__LPSPI3_SOUT 0x0
+ IMX7ULP_PAD_PTF18__LPSPI3_SCK 0x0
+ IMX7ULP_PAD_PTF19__LPSPI3_PCS0 0x0
+ >;
+ };
+
pinctrl_usbotg1_vbus: otg1vbusgrp {
fsl,pins = <
IMX7ULP_PAD_PTC0__PTC0 0x20000
@@ -108,7 +550,6 @@
pinctrl_usbotg1_id: otg1idgrp {
fsl,pins = <
IMX7ULP_PAD_PTC13__USB0_ID 0x10003
- IMX7ULP_PAD_PTC16__USB1_OC2 0x10003
>;
};
@@ -124,9 +565,51 @@
>;
};
+ pinctrl_usdhc0_8bit: usdhc0grp_8bit {
+ fsl,pins = <
+ IMX7ULP_PAD_PTD1__SDHC0_CMD 0x43
+ IMX7ULP_PAD_PTD2__SDHC0_CLK 0x10042
+ IMX7ULP_PAD_PTD3__SDHC0_D7 0x43
+ IMX7ULP_PAD_PTD4__SDHC0_D6 0x43
+ IMX7ULP_PAD_PTD5__SDHC0_D5 0x43
+ IMX7ULP_PAD_PTD6__SDHC0_D4 0x43
+ IMX7ULP_PAD_PTD7__SDHC0_D3 0x43
+ IMX7ULP_PAD_PTD8__SDHC0_D2 0x43
+ IMX7ULP_PAD_PTD9__SDHC0_D1 0x43
+ IMX7ULP_PAD_PTD10__SDHC0_D0 0x43
+ IMX7ULP_PAD_PTD11__SDHC0_DQS 0x42
+ >;
+ };
+
pinctrl_usdhc0_rst: usdhc0-gpio-rst-grp {
fsl,pins = <
IMX7ULP_PAD_PTD0__PTD0 0x3
>;
};
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTE3__SDHC1_CMD 0x43
+ IMX7ULP_PAD_PTE2__SDHC1_CLK 0x10042
+ IMX7ULP_PAD_PTE1__SDHC1_D0 0x43
+ IMX7ULP_PAD_PTE0__SDHC1_D1 0x43
+ IMX7ULP_PAD_PTE5__SDHC1_D2 0x43
+ IMX7ULP_PAD_PTE4__SDHC1_D3 0x43
+ >;
+ };
+
+ pinctrl_usdhc1_rst: usdhc1grp_rst {
+ fsl,pins = <
+ IMX7ULP_PAD_PTE11__PTE11 0x20000 /* USDHC1 RST */
+ IMX7ULP_PAD_PTE13__PTE13 0x10003 /* USDHC1 CD */
+ IMX7ULP_PAD_PTE12__PTE12 0x10003 /* USDHC1 WP */
+ IMX7ULP_PAD_PTE14__SDHC1_VS 0x43 /* USDHC1 VSEL */
+ >;
+ };
+
+ pinctrl_dsi_hdmi: dsi_hdmi_grp {
+ fsl,pins = <
+ IMX7ULP_PAD_PTC18__PTC18 0x10003 /* DSI_HDMI_INT */
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-emmc.dts b/arch/arm/boot/dts/imx7ulp-evkb-emmc.dts
new file mode 100644
index 000000000000..ca6acd44de19
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-emmc.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 NXP.
+ *
+ * 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 "imx7ulp-evkb.dts"
+
+/* To support eMMC HS200/HS400, need to do the following reowrk:
+ * 1,remove TF sd slot, replace eMMC chip
+ * 2,fix eMMC I/O voltage to 1.8v, remove R183, short TP3 and TP89
+ * 3,add R107, make eMMC boot work
+ */
+&usdhc0 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc0_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc0_8bit>;
+ pinctrl-2 = <&pinctrl_usdhc0_8bit>;
+ pinctrl-3 = <&pinctrl_usdhc0_8bit>;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-lpuart.dts b/arch/arm/boot/dts/imx7ulp-evkb-lpuart.dts
new file mode 100644
index 000000000000..1a5da007edf6
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-lpuart.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx7ulp-evkb.dts"
+
+&lpi2c7 {
+ status = "disabled";
+};
+
+&lpuart7 { /* Uart test */
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-mipi.dts b/arch/arm/boot/dts/imx7ulp-evkb-mipi.dts
new file mode 100644
index 000000000000..0ebf73f2618a
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-mipi.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 NXP.
+ *
+ * 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 "imx7ulp-evkb.dts"
+#include "imx7ulp-evk-mipi.dtsi"
+
+&lpi2c7 {
+ focaltech@38 {
+ status = "disabled";
+ };
+
+ goodix@14 {
+ compatible = "goodix,gt911";
+ reg = <0x14>;
+ interrupt-parent = <&gpio_ptf>;
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ irq-gpios = <&gpio_ptf 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio_ptf 1 GPIO_ACTIVE_HIGH>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-rm68191-qhd.dts b/arch/arm/boot/dts/imx7ulp-evkb-rm68191-qhd.dts
new file mode 100644
index 000000000000..c482087c08e0
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-rm68191-qhd.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018 NXP.
+ *
+ * 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 "imx7ulp-evkb-mipi.dts"
+
+&mipi_dsi {
+ lcd_panel = "ROCKTECH-QHD-RK055IQH042";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-rm68200-wxga.dts b/arch/arm/boot/dts/imx7ulp-evkb-rm68200-wxga.dts
new file mode 100644
index 000000000000..28b83c388101
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-rm68200-wxga.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018 NXP.
+ *
+ * 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 "imx7ulp-evkb-mipi.dts"
+
+&mipi_dsi {
+ lcd_panel = "ROCKTECH-WXGA-RK055AHD042";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-sd1.dts b/arch/arm/boot/dts/imx7ulp-evkb-sd1.dts
new file mode 100644
index 000000000000..8984a6ace291
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-sd1.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx7ulp-evkb.dts"
+
+/ {
+ regulators {
+ reg_vsd_3v3b: regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3B";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio_pte 11 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
+ enable-active-high;
+ };
+ };
+};
+
+&lpuart6 {
+ status = "disabled";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_usdhc1_rst>;
+ pinctrl-1 = <&pinctrl_usdhc1 &pinctrl_usdhc1_rst>;
+ pinctrl-2 = <&pinctrl_usdhc1 &pinctrl_usdhc1_rst>;
+ pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_usdhc1_rst>;
+ cd-gpios = <&gpio_pte 13 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio_pte 12 GPIO_ACTIVE_HIGH>;
+ fsl,delay-line = <15>;
+ vmmc-supply = <&reg_vsd_3v3b>;
+ /delete-property/non-removable;
+ /delete-property/pm-ignore-notify;
+ /delete-property/keep-power-in-suspend;
+ /delete-property/non-removable;
+ /delete-property/no-1-8-v;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-sensors-to-i2c5.dts b/arch/arm/boot/dts/imx7ulp-evkb-sensors-to-i2c5.dts
new file mode 100644
index 000000000000..83a712b9b4f3
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-sensors-to-i2c5.dts
@@ -0,0 +1,21 @@
+
+#include "imx7ulp-evkb.dts"
+
+&lpi2c5 {
+
+ fxas2100x@20 {
+ compatible = "fsl,fxas2100x";
+ reg = <0x20>;
+ };
+
+ fxos8700@1e {
+ compatible = "fsl,fxos8700";
+ reg = <0x1e>;
+ };
+
+ mpl3115@60 {
+ compatible = "fsl,mpl3115";
+ reg = <0x60>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb-spi-slave.dts b/arch/arm/boot/dts/imx7ulp-evkb-spi-slave.dts
new file mode 100644
index 000000000000..83cb121ff50a
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb-spi-slave.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ *
+ * 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 "imx7ulp-evkb.dts"
+
+/delete-node/&spidev0;
+
+&pinctrl_lpspi3 {
+ fsl,pins = <
+ IMX7ULP_PAD_PTF16__LPSPI3_SIN 0x0
+ IMX7ULP_PAD_PTF17__LPSPI3_SOUT 0x0
+ IMX7ULP_PAD_PTF18__LPSPI3_SCK 0x0
+ IMX7ULP_PAD_PTF19__LPSPI3_PCS0 0x0
+ >;
+};
+
+&lpspi3 {
+ #address-cells = <0>;
+ pinctrl-0 = <&pinctrl_lpspi3>;
+ pinctrl-1 = <&pinctrl_lpspi3>;
+ /delete-property/ cs-gpios;
+
+ spi-slave;
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evkb.dts b/arch/arm/boot/dts/imx7ulp-evkb.dts
new file mode 100644
index 000000000000..37df89558349
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evkb.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * 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 "imx7ulp-evk.dts"
+
+/ {
+ model = "NXP i.MX7ULP EVKB";
+ compatible = "fsl,imx7ulp-evkb", "fsl,imx7ulp", "Generic DT based system";
+
+ regulators {
+ reg_sd1_vmmc: sd1_regulator {
+ status = "disabled";
+ };
+ };
+
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&rpmsg_gpio0 14 GPIO_ACTIVE_LOW>;
+ post-power-on-delay-ms = <80>;
+ };
+};
+
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /delete-property/ vmmc-supply;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ cap-power-off-card;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index 0108b63df77d..471cd61cb6de 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -41,9 +41,41 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <0xf00>;
+ operating-points = <
+ /* KHz uV */
+ 720000 1125000
+ 500210 1025000
+ >;
+ clocks = <&smc1 IMX7ULP_CLK_ARM>,
+ <&scg1 IMX7ULP_CLK_CORE_DIV>,
+ <&scg1 IMX7ULP_CLK_SYS_SEL>,
+ <&scg1 IMX7ULP_CLK_HSRUN_SYS_SEL>,
+ <&scg1 IMX7ULP_CLK_HSRUN_CORE_DIV>,
+ <&scg1 IMX7ULP_CLK_SPLL_PFD0>,
+ <&scg1 IMX7ULP_CLK_SPLL_SEL>,
+ <&scg1 IMX7ULP_CLK_FIRC>,
+ <&scg1 IMX7ULP_CLK_SPLL>;
+ clock-names = "arm", "core_div", "sys_sel", "hsrun_sys_sel",
+ "hsrun_core", "spll_pfd0", "spll_sel", "firc",
+ "spll";
};
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0xC000000>;
+ alignment = <0x2000>;
+ linux,cma-default;
+ };
+ };
+
intc: interrupt-controller@40021000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
@@ -87,11 +119,14 @@
#clock-cells = <0>;
};
- mpll: clock-mpll {
- compatible = "fixed-clock";
- clock-frequency = <480000000>;
- clock-output-names = "mpll";
- #clock-cells = <0>;
+ sram: sram@20000000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x1fffc000 0x4000>;
+ };
+
+ caam_sm: caam-sm@26000000 {
+ compatible = "fsl,imx6q-caam-sm";
+ reg = <0x26000000 0x8000>;
};
ahbbridge0: bus@40000000 {
@@ -129,6 +164,62 @@
<&pcc2 IMX7ULP_CLK_DMA_MUX1>;
};
+ mu: mu@40220000 {
+ compatible = "fsl,imx7ulp-mu";
+ reg = <0x40220000 0x1000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ };
+
+ nmi: nmi@40220000 {
+ compatible = "fsl,imx7ulp-nmi";
+ reg = <0x40220000 0x1000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+ };
+
+ mu_lp: mu_lp@40220000 {
+ compatible = "fsl,imx7ulp-mu-lp", "fsl,imx6sx-mu-lp";
+ reg = <0x40220000 0x1000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+ };
+
+ lpspi2: spi@40290000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x40290000 0x10000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_LPSPI2>,
+ <&pcc2 IMX7ULP_CLK_DUMMY>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_LPSPI2>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ assigned-clock-rates = <48000000>;
+ dmas = <&edma1 0 26>, <&edma1 0 25>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
+ lpspi3: spi@402A0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x402A0000 0x10000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_LPSPI3>,
+ <&pcc2 IMX7ULP_CLK_DUMMY>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_LPSPI3>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ assigned-clock-rates = <48000000>;
+ dmas = <&edma1 0 28>, <&edma1 0 27>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
crypto: crypto@40240000 {
compatible = "fsl,sec-v4.0";
#address-cells = <1>;
@@ -152,6 +243,31 @@
};
};
+ lpi2c4: lpi2c4@402b0000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x402b0000 0x10000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>,
+ <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+ };
+
+ lpi2c5: lpi2c5@402c0000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x402c0000 0x10000>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>,
+ <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ assigned-clock-rates = <48000000>;
+ };
+
lpuart4: serial@402d0000 {
compatible = "fsl,imx7ulp-lpuart";
reg = <0x402d0000 0x1000>;
@@ -171,8 +287,10 @@
clocks = <&pcc2 IMX7ULP_CLK_LPUART5>;
clock-names = "ipg";
assigned-clocks = <&pcc2 IMX7ULP_CLK_LPUART5>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
assigned-clock-rates = <48000000>;
+ dmas = <&edma1 0 20>, <&edma1 0 19>;
+ dma-names = "tx","rx";
status = "disabled";
};
@@ -220,6 +338,7 @@
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pcc2 IMX7ULP_CLK_USB_PHY>;
#phy-cells = <0>;
+ nxp,sim = <&sim>;
};
usdhc0: mmc@40370000 {
@@ -230,8 +349,9 @@
<&scg1 IMX7ULP_CLK_NIC1_DIV>,
<&pcc2 IMX7ULP_CLK_USDHC0>;
clock-names = "ipg", "ahb", "per";
- assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC0>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>;
+ assigned-clocks = <&scg1 IMX7ULP_CLK_APLL_PFD1>, <&pcc2 IMX7ULP_CLK_USDHC0>;
+ assigned-clock-parents = <0>, <&scg1 IMX7ULP_CLK_APLL_PFD1>;
+ assigned-clock-rates = <0>, <352800000>;
bus-width = <4>;
fsl,tuning-start-tap = <20>;
fsl,tuning-step = <2>;
@@ -246,8 +366,9 @@
<&scg1 IMX7ULP_CLK_NIC1_DIV>,
<&pcc2 IMX7ULP_CLK_USDHC1>;
clock-names = "ipg", "ahb", "per";
- assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC1>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>;
+ assigned-clocks = <&scg1 IMX7ULP_CLK_APLL_PFD1>, <&pcc2 IMX7ULP_CLK_USDHC1>;
+ assigned-clock-parents = <0>, <&scg1 IMX7ULP_CLK_APLL_PFD1>;
+ assigned-clock-rates = <0>, <352800000>;
bus-width = <4>;
fsl,tuning-start-tap = <20>;
fsl,tuning-step = <2>;
@@ -258,12 +379,37 @@
compatible = "fsl,imx7ulp-scg1";
reg = <0x403e0000 0x10000>;
clocks = <&rosc>, <&sosc>, <&sirc>,
- <&firc>, <&upll>, <&mpll>;
+ <&firc>, <&upll>;
clock-names = "rosc", "sosc", "sirc",
- "firc", "upll", "mpll";
+ "firc", "upll";
#clock-cells = <1>;
};
+ wdog1: wdog@403D0000 {
+ compatible = "fsl,imx7ulp-wdt";
+ reg = <0x403D0000 0x10000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_WDG1>;
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_WDG1>;
+ assigned-clocks-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ /*
+ * As the 1KHz LPO clock rate is not trimed,the actually clock
+ * is about 667Hz, so the init timeout 60s should set 40*1000
+ * in the TOVAL register.
+ */
+ timeout-sec = <40>;
+ };
+
+ wdog2: wdog@40430000 {
+ compatible = "fsl,imx7ulp-wdt";
+ reg = <0x40430000 0x10000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc2 IMX7ULP_CLK_WDG2>;
+ assigned-clocks = <&pcc2 IMX7ULP_CLK_WDG2>;
+ assigned-clocks-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
+ timeout-sec = <40>;
+ };
+
pcc2: clock-controller@403f0000 {
compatible = "fsl,imx7ulp-pcc2";
reg = <0x403f0000 0x10000>;
@@ -276,18 +422,22 @@
<&scg1 IMX7ULP_CLK_APLL_PFD0>,
<&scg1 IMX7ULP_CLK_UPLL>,
<&scg1 IMX7ULP_CLK_SOSC_BUS_CLK>,
- <&scg1 IMX7ULP_CLK_MIPI_PLL>,
<&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>,
<&scg1 IMX7ULP_CLK_ROSC>,
<&scg1 IMX7ULP_CLK_SPLL_BUS_CLK>;
clock-names = "nic1_bus_clk", "nic1_clk", "ddr_clk",
"apll_pfd2", "apll_pfd1", "apll_pfd0",
- "upll", "sosc_bus_clk", "mpll",
+ "upll", "sosc_bus_clk",
"firc_bus_clk", "rosc", "spll_bus_clk";
assigned-clocks = <&pcc2 IMX7ULP_CLK_LPTPM5>;
assigned-clock-parents = <&scg1 IMX7ULP_CLK_SOSC_BUS_CLK>;
};
+ pmc1: pmc1@40400000 {
+ compatible = "fsl,imx7ulp-pmc1";
+ reg = <0x40400000 0x1000>;
+ };
+
smc1: clock-controller@40410000 {
compatible = "fsl,imx7ulp-smc1";
reg = <0x40410000 0x1000>;
@@ -309,13 +459,12 @@
<&scg1 IMX7ULP_CLK_APLL_PFD0>,
<&scg1 IMX7ULP_CLK_UPLL>,
<&scg1 IMX7ULP_CLK_SOSC_BUS_CLK>,
- <&scg1 IMX7ULP_CLK_MIPI_PLL>,
<&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>,
<&scg1 IMX7ULP_CLK_ROSC>,
<&scg1 IMX7ULP_CLK_SPLL_BUS_CLK>;
clock-names = "nic1_bus_clk", "nic1_clk", "ddr_clk",
"apll_pfd2", "apll_pfd1", "apll_pfd0",
- "upll", "sosc_bus_clk", "mpll",
+ "upll", "sosc_bus_clk",
"firc_bus_clk", "rosc", "spll_bus_clk";
};
};
@@ -331,10 +480,11 @@
compatible = "fsl,imx7ulp-lpi2c";
reg = <0x40a40000 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
- clock-names = "ipg";
+ clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>,
+ <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+ clock-names = "per", "ipg";
assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
assigned-clock-rates = <48000000>;
status = "disabled";
};
@@ -343,10 +493,11 @@
compatible = "fsl,imx7ulp-lpi2c";
reg = <0x40a50000 0x10000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
- clock-names = "ipg";
+ clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>,
+ <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+ clock-names = "per", "ipg";
assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
assigned-clock-rates = <48000000>;
status = "disabled";
};
@@ -358,8 +509,10 @@
clocks = <&pcc3 IMX7ULP_CLK_LPUART6>;
clock-names = "ipg";
assigned-clocks = <&pcc3 IMX7ULP_CLK_LPUART6>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
assigned-clock-rates = <48000000>;
+ dmas = <&edma1 0 22>, <&edma1 0 21>;
+ dma-names = "tx","rx";
status = "disabled";
};
@@ -370,8 +523,34 @@
clocks = <&pcc3 IMX7ULP_CLK_LPUART7>;
clock-names = "ipg";
assigned-clocks = <&pcc3 IMX7ULP_CLK_LPUART7>;
- assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>;
assigned-clock-rates = <48000000>;
+ dmas = <&edma1 0 24>, <&edma1 0 23>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
+ mipi_dsi: mipi_dsi@40a90000 {
+ compatible = "fsl,imx7ulp-mipi-dsi";
+ reg = <0x40a90000 0x1000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc3 IMX7ULP_CLK_DSI>;
+ clock-names = "mipi_dsi_clk";
+ data-lanes-num = <2>;
+ phy-ref-clkfreq = <24000000>;
+ max-data-rate = <800000000>;
+ sim = <&sim>;
+ status = "disabled";
+ };
+
+ lcdif: lcdif@40aa0000 {
+ compatible = "fsl,imx7ulp-lcdif";
+ reg = <0x40aa0000 0x1000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scg1 IMX7ULP_CLK_DUMMY>,
+ <&pcc3 IMX7ULP_CLK_LCDIF>,
+ <&scg1 IMX7ULP_CLK_DUMMY>;
+ clock-names = "axi", "pix", "disp_axi";
status = "disabled";
};
@@ -441,6 +620,28 @@
clock-names = "gpio", "port";
gpio-ranges = <&iomuxc1 0 96 20>;
};
+
+ gpu: gpu@41800000 {
+ compatible = "fsl,imx7ulp-gpu", "fsl,imx6q-gpu";
+ reg = <0x41800000 0x80000>, <0x41880000 0x80000>,
+ <0x60000000 0x40000000>, <0x0 0x4000000>;
+ reg-names = "iobase_3d", "iobase_2d",
+ "phys_baseaddr", "contiguous_mem";
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_3d", "irq_2d";
+ clocks = <&pcc3 IMX7ULP_CLK_GPU3D>,
+ <&scg1 IMX7ULP_CLK_DUMMY>,
+ <&scg1 IMX7ULP_CLK_GPU_DIV>,
+ <&pcc3 IMX7ULP_CLK_GPU2D>,
+ <&scg1 IMX7ULP_CLK_NIC1_DIV>;
+ clock-names = "gpu3d_clk", "gpu3d_shader_clk",
+ "gpu3d_axi_clk", "gpu2d_clk",
+ "gpu2d_axi_clk";
+ assigned-clocks = <&scg1 IMX7ULP_CLK_APLL_PFD2>, <&pcc3 IMX7ULP_CLK_GPU3D>, <&pcc3 IMX7ULP_CLK_GPU2D>;
+ assigned-clock-parents = <0>, <&scg1 IMX7ULP_CLK_APLL_PFD2>, <&scg1 IMX7ULP_CLK_APLL_PFD2>;
+ assigned-clock-rates = <400000000>, <400000000>, <400000000>;
+ };
};
m4aips1: bus@41080000 {
@@ -450,6 +651,11 @@
reg = <0x41080000 0x80000>;
ranges;
+ pmc0: pmc0@410a1000 {
+ compatible = "fsl,imx7ulp-pmc0";
+ reg = <0x410a1000 0x1000>;
+ };
+
sim: sim@410a3000 {
compatible = "fsl,imx7ulp-sim", "syscon";
reg = <0x410a3000 0x1000>;
@@ -461,4 +667,27 @@
clocks = <&scg1 IMX7ULP_CLK_DUMMY>;
};
};
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx7ulp-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";
+ };
+
+ heartbeat-rpmsg {
+ compatible = "fsl,heartbeat-rpmsg";
+ };
+
+ rtc-rpmsg {
+ compatible = "fsl,imx-rpmsg-rtc";
+ };
+
};
diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts
index 74a67604876c..ee718b5b7b0e 100644
--- a/arch/arm/boot/dts/ls1021a-qds.dts
+++ b/arch/arm/boot/dts/ls1021a-qds.dts
@@ -126,6 +126,21 @@
};
};
+&qspi {
+ num-cs = <2>;
+ status = "okay";
+
+ qflash0: s25fl128s@0 {
+ compatible = "spansion,m25p80";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
+
&enet0 {
tbi-handle = <&tbi0>;
phy-handle = <&sgmii_phy1c>;
@@ -150,6 +165,10 @@
status = "okay";
};
+&esdhc {
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index 9b1fe99d55b1..0ca4ebfc0304 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -144,6 +144,21 @@
};
};
+&qspi {
+ num-cs = <2>;
+ status = "okay";
+
+ qflash0: n25q128a13@0 {
+ compatible = "n25q128a13", "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
+
&enet0 {
tbi-handle = <&tbi0>;
phy-handle = <&sgmii_phy2>;
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c62fcca7b426..8a9f132a32c1 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -66,6 +66,7 @@
serial4 = &lpuart4;
serial5 = &lpuart5;
sysclk = &sysclk;
+ rtc1 = &ftm_alarm0;
};
cpus {
@@ -167,12 +168,13 @@
ifc: ifc@1530000 {
compatible = "fsl,ifc", "simple-bus";
reg = <0x0 0x1530000 0x0 0x10000>;
+ big-endian;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
};
dcfg: dcfg@1ee0000 {
compatible = "fsl,ls1021a-dcfg", "syscon";
- reg = <0x0 0x1ee0000 0x0 0x10000>;
+ reg = <0x0 0x1ee0000 0x0 0x1000>;
big-endian;
};
@@ -371,7 +373,7 @@
};
i2c0: i2c@2180000 {
- compatible = "fsl,vf610-i2c";
+ compatible = "fsl,vf610-i2c", "fsl,ls1021a-vf610-i2c";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2180000 0x0 0x10000>;
@@ -380,11 +382,12 @@
clocks = <&clockgen 4 1>;
dma-names = "tx", "rx";
dmas = <&edma0 1 39>, <&edma0 1 38>;
+ fsl-scl-gpio = <&gpio3 23 0>;
status = "disabled";
};
i2c1: i2c@2190000 {
- compatible = "fsl,vf610-i2c";
+ compatible = "fsl,vf610-i2c", "fsl,ls1021a-vf610-i2c";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2190000 0x0 0x10000>;
@@ -393,6 +396,7 @@
clocks = <&clockgen 4 1>;
dma-names = "tx", "rx";
dmas = <&edma0 1 37>, <&edma0 1 36>;
+ fsl-scl-gpio = <&gpio3 23 0>;
status = "disabled";
};
@@ -678,8 +682,9 @@
reg = <0x0 0x2b50000 0x0 0x10000>;
interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen 4 1>, <&clockgen 4 1>,
- <&clockgen 4 1>, <&clockgen 4 1>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ <&clockgen 4 1>, <&clockgen 4 1>,
+ <&clockgen 4 1>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 1 47>,
<&edma0 1 46>;
@@ -692,8 +697,9 @@
reg = <0x0 0x2b60000 0x0 0x10000>;
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen 4 1>, <&clockgen 4 1>,
- <&clockgen 4 1>, <&clockgen 4 1>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ <&clockgen 4 1>, <&clockgen 4 1>,
+ <&clockgen 4 1>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 1 45>,
<&edma0 1 44>;
@@ -861,7 +867,10 @@
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
+ usb3-lpm-capable;
+ snps,dis-u1u2-when-u3-quirk;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
+ snps,host-vbus-glitches;
};
pcie@3400000 {
@@ -869,7 +878,9 @@
reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */
0x40 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupt-names = "pme", "aer";
fsl,pcie-scfg = <&scfg 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -893,7 +904,9 @@
reg = <0x00 0x03500000 0x0 0x00010000 /* controller registers */
0x48 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupt-names = "pme", "aer";
fsl,pcie-scfg = <&scfg 1>;
#address-cells = <3>;
#size-cells = <2>;
@@ -983,5 +996,24 @@
big-endian;
};
+ rcpm: rcpm@1ee2140 {
+ compatible = "fsl,ls1021a-rcpm", "fsl,qoriq-rcpm-2.1+";
+ reg = <0x0 0x1ee2140 0x0 0x8>;
+ #fsl,rcpm-wakeup-cells = <2>;
+
+ /*
+ * The second and third entry compose an alt offset
+ * address for IPPDEXPCR1(SCFG_SPARECR8)
+ */
+ fsl,ippdexpcr1-alt-addr = <&scfg 0x0 0x51c>;
+ };
+
+ ftm_alarm0: timer0@29d0000 {
+ compatible = "fsl,ls1021a-ftm-alarm";
+ reg = <0x0 0x29d0000 0x0 0x10000>;
+ fsl,rcpm-wakeup = <&rcpm 0x0 0x20000000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ big-endian;
+ };
};
};
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index dabb80453249..8233e5a4f615 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -2,7 +2,7 @@ CONFIG_KERNEL_LZO=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_PREEMPT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
@@ -40,9 +40,6 @@ CONFIG_SOC_IMX6UL=y
CONFIG_SOC_IMX7D=y
CONFIG_SOC_IMX7ULP=y
CONFIG_SOC_VF610=y
-CONFIG_PCI=y
-CONFIG_PCI_MSI=y
-CONFIG_PCI_IMX6=y
CONFIG_SMP=y
CONFIG_ARM_PSCI=y
CONFIG_HIGHMEM=y
@@ -58,6 +55,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_IMX6Q_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=y
+CONFIG_ARM_IMX7ULP_CPUFREQ=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
@@ -71,33 +69,47 @@ 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_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_NETFILTER=y
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC2=y
CONFIG_CAN=y
CONFIG_CAN_FLEXCAN=y
CONFIG_BT=y
-CONFIG_BT_BNEP=m
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=y
CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_MRVL=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_BT_MRVL=y
+CONFIG_BT_MRVL_SDIO=y
CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
-CONFIG_RFKILL=y
-CONFIG_RFKILL_INPUT=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_IMX6=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
-CONFIG_CMA_SIZE_MBYTES=64
CONFIG_IMX_WEIM=y
CONFIG_CONNECTOR=y
CONFIG_MTD=y
@@ -108,16 +120,14 @@ 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_DATAFLASH=y
-CONFIG_MTD_M25P80=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_MTD_NAND_VF610_NFC=y
CONFIG_MTD_NAND_MXC=y
CONFIG_MTD_SPI_NOR=y
-CONFIG_SPI_FSL_QUADSPI=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_MTD_UBI_BLOCK=y
@@ -163,9 +173,7 @@ CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_SMSC95XX=y
CONFIG_USB_NET_MCS7830=y
CONFIG_BRCMFMAC=m
-CONFIG_MWIFIEX=m
-CONFIG_MWIFIEX_SDIO=m
-CONFIG_MWIFIEX_PCIE=m
+CONFIG_HOSTAP=y
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
@@ -173,6 +181,7 @@ CONFIG_WLCORE_SDIO=m
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_RPMSG=y
CONFIG_KEYBOARD_SNVS_PWRKEY=y
CONFIG_KEYBOARD_IMX=y
CONFIG_MOUSE_PS2=m
@@ -181,6 +190,8 @@ CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=y
CONFIG_TOUCHSCREEN_EGALAX=y
CONFIG_TOUCHSCREEN_GOODIX=y
+CONFIG_TOUCHSCREEN_ELAN_TS=y
+CONFIG_TOUCHSCREEN_FTS=y
CONFIG_TOUCHSCREEN_MAX11801=y
CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
CONFIG_TOUCHSCREEN_EDT_FT5X06=y
@@ -192,6 +203,8 @@ CONFIG_TOUCHSCREEN_SX8654=y
CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MMA8450=y
+CONFIG_INPUT_MPL3115=y
+CONFIG_INPUT_ISL29023=y
CONFIG_SERIO_SERPORT=m
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_IMX=y
@@ -208,11 +221,19 @@ CONFIG_I2C_ALGOPCF=m
CONFIG_I2C_ALGOPCA=m
CONFIG_I2C_GPIO=y
CONFIG_I2C_IMX=y
+CONFIG_I2C_IMX_LPI2C=y
CONFIG_SPI=y
+CONFIG_SPI_FSL_QUADSPI=y
+CONFIG_SPI_FSL_LPSPI=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
CONFIG_SPI_FSL_DSPI=y
+CONFIG_SPI_SLAVE=y
+CONFIG_SPI_SLAVE_TIME=y
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_IMX_RPMSG=y
CONFIG_GPIO_SIOX=m
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_MC9S08DZ60=y
@@ -224,24 +245,35 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
CONFIG_POWER_SUPPLY=y
+CONFIG_SABRESD_MAX8903=y
+CONFIG_SENSORS_FXOS8700=y
+CONFIG_SENSORS_FXAS2100X=y
+CONFIG_SENSOR_FXLS8471=y
+CONFIG_SENSOR_IMX_RPMSG=y
CONFIG_SENSORS_MC13783_ADC=y
CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_MAX17135=y
CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_THERMAL=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_CPU_THERMAL=y
CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
CONFIG_WATCHDOG=y
-CONFIG_DA9062_WATCHDOG=y
CONFIG_DA9063_WATCHDOG=m
+CONFIG_DA9062_WATCHDOG=y
CONFIG_RN5T618_WATCHDOG=y
CONFIG_IMX2_WDT=y
+CONFIG_IMX7ULP_WDT=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9062=y
CONFIG_MFD_DA9063=y
CONFIG_MFD_MC13XXX_SPI=y
CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_MAX17135=y
CONFIG_MFD_RN5T618=y
+CONFIG_MFD_SI476X_CORE=y
CONFIG_MFD_STMPE=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -250,8 +282,10 @@ CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9062=y
CONFIG_REGULATOR_DA9063=y
CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX17135=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
+CONFIG_REGULATOR_PF1550_RPMSG=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_RN5T618=y
CONFIG_RC_CORE=y
@@ -259,37 +293,54 @@ CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_CIR=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_VIDEO_MUX=y
-CONFIG_SOC_CAMERA=y
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_MIPI_CSI=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5640_V2=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_CAMERA_OV5640_MIPI_V2=m
+CONFIG_MXC_TVIN_ADV7180=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_CODA=m
CONFIG_VIDEO_IMX_PXP=y
-# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
CONFIG_VIDEO_ADV7180=m
CONFIG_VIDEO_OV2680=m
-CONFIG_VIDEO_OV5640=m
CONFIG_VIDEO_OV5645=m
-CONFIG_IMX_IPUV3_CORE=y
+CONFIG_RADIO_SI476X=y
CONFIG_DRM=y
CONFIG_DRM_MSM=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
-CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
-CONFIG_DRM_DW_HDMI_CEC=y
-CONFIG_DRM_IMX=y
-CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
-CONFIG_DRM_IMX_TVE=y
-CONFIG_DRM_IMX_LDB=y
-CONFIG_DRM_IMX_HDMI=y
-CONFIG_DRM_ETNAVIV=y
-CONFIG_DRM_MXSFB=y
-CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_FB_MXC_EINK_V2_PANEL=y
+CONFIG_FB_MXC_MIPI_DSI=y
+CONFIG_FB_MXC_MIPI_DSI_NORTHWEST=y
+CONFIG_FB_MXC_MIPI_DSI_SAMSUNG=y
+CONFIG_FB_MXC_ADV7535=y
+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
+CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E=y
+CONFIG_FB_MXC_RK_PANEL_RK055AHD042=y
+CONFIG_FB_MXC_RK_PANEL_RK055IQH042=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_FB_MXS_SII902X=y
+CONFIG_FB_MXC_DCIC=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_L4F00242T03=y
CONFIG_LCD_PLATFORM=y
@@ -301,26 +352,31 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_SOC=y
-CONFIG_SND_SOC_FSL_ASRC=y
CONFIG_SND_IMX_SOC=y
CONFIG_SND_SOC_PHYCORE_AC97=y
CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_WM8960=y
+CONFIG_SND_SOC_IMX_SII902X=y
+CONFIG_SND_SOC_IMX_WM8958=y
+CONFIG_SND_SOC_IMX_CS42888=y
+CONFIG_SND_SOC_IMX_WM8962=y
+CONFIG_SND_SOC_IMX_RPMSG=y
CONFIG_SND_SOC_IMX_ES8328=y
CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MQS=y
CONFIG_SND_SOC_IMX_SPDIF=y
CONFIG_SND_SOC_IMX_MC13783=y
-CONFIG_SND_SOC_FSL_ASOC_CARD=y
+CONFIG_SND_SOC_IMX_SI476X=y
+CONFIG_SND_SOC_IMX_HDMI=y
CONFIG_SND_SOC_AC97_CODEC=y
-CONFIG_SND_SOC_CS42XX8_I2C=y
CONFIG_SND_SOC_TLV320AIC3X=y
-CONFIG_SND_SOC_WM8960=y
-CONFIG_SND_SOC_WM8962=y
CONFIG_SND_SIMPLE_CARD=y
CONFIG_HID_MULTITOUCH=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ACM=m
CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
@@ -335,7 +391,7 @@ CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_FSL_USB2=y
-CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
@@ -365,6 +421,8 @@ CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MXC_SIM=y
+CONFIG_MXC_SIMv2=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
@@ -388,26 +446,29 @@ CONFIG_RTC_DRV_MC13XXX=y
CONFIG_RTC_DRV_MXC=y
CONFIG_RTC_DRV_MXC_V2=y
CONFIG_RTC_DRV_SNVS=y
+CONFIG_RTC_DRV_IMX_RPMSG=y
CONFIG_DMADEVICES=y
CONFIG_FSL_EDMA=y
CONFIG_IMX_SDMA=y
CONFIG_MXS_DMA=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_MXC_PXP_V3=y
CONFIG_DMATEST=m
CONFIG_STAGING=y
CONFIG_STAGING_MEDIA=y
-CONFIG_VIDEO_IMX_MEDIA=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_IIO=y
-CONFIG_MMA8452=y
CONFIG_IMX7D_ADC=y
CONFIG_VF610_ADC=y
-CONFIG_SENSORS_ISL29018=y
-CONFIG_MAG3110=y
-CONFIG_MPL3115=y
+CONFIG_SENSORS_MAG3110=y
CONFIG_PWM=y
CONFIG_PWM_FSL_FTM=y
CONFIG_PWM_IMX27=y
CONFIG_PWM_IMX_TPM=y
+CONFIG_PHY_MIXEL_LVDS=y
+CONFIG_PHY_MIXEL_LVDS_COMBO=y
+CONFIG_MAILBOX=y
+CONFIG_IMX_MBOX=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_VF610_OCOTP=y
CONFIG_NVMEM_SNVS_LPGPR=y
@@ -416,6 +477,11 @@ CONFIG_OPTEE=y
CONFIG_MUX_MMIO=y
CONFIG_SIOX=m
CONFIG_SIOX_BUS_GPIO=m
+CONFIG_MXC_IPU=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_MLB150=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_MXC_HDMI_CEC=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
@@ -434,6 +500,7 @@ CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
@@ -448,13 +515,40 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_TLS=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+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_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=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_FSL_CAAM_SECVIO=y
CONFIG_CRYPTO_DEV_SAHARA=y
CONFIG_CRYPTO_DEV_MXS_DCP=y
CONFIG_CRC_CCITT=m
CONFIG_CRC_T10DIF=y
CONFIG_CRC7=m
CONFIG_LIBCRC32C=m
+CONFIG_DMA_CMA=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
new file mode 100644
index 000000000000..30792d235072
--- /dev/null
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -0,0 +1,579 @@
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_MEMCG=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX50=y
+CONFIG_SOC_IMX51=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SLL=y
+CONFIG_SOC_IMX6SX=y
+CONFIG_SOC_IMX6UL=y
+CONFIG_SOC_IMX7D=y
+CONFIG_SOC_IMX7ULP=y
+CONFIG_SOC_VF610=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_ARM_PSCI=y
+CONFIG_HIGHMEM=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_KEXEC=y
+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_ARM_IMX6Q_CPUFREQ=y
+CONFIG_ARM_IMX_CPUFREQ_DT=y
+CONFIG_ARM_IMX7ULP_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+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_SECCOMP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NETFILTER=y
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC2=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_MRVL=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_BT_MRVL=y
+CONFIG_BT_MRVL_SDIO=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_IMX6=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_FW_LOADER_USER_HELPER=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+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=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_VF610_NFC=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SENSORS_FXOS8700=y
+CONFIG_SENSORS_FXAS2100X=y
+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_PLATFORM=y
+CONFIG_AHCI_IMX=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_CS89x0=y
+CONFIG_CS89x0_PLATFORM=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_E1000E=y
+# 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_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=y
+CONFIG_USB_LAN78XX=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_BRCMFMAC=m
+CONFIG_HOSTAP=y
+CONFIG_MXMWIFIEX=m
+CONFIG_WL12XX=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SDIO=m
+# CONFIG_WILINK_PLATFORM_DATA is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_RPMSG=y
+CONFIG_KEYBOARD_IMX=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_TOUCHSCREEN_EGALAX=y
+CONFIG_TOUCHSCREEN_ELAN_TS=y
+CONFIG_TOUCHSCREEN_GOODIX=y
+CONFIG_TOUCHSCREEN_MAX11801=y
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
+CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_TOUCHSCREEN_TSC2004=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_TOUCHSCREEN_SX8654=y
+CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
+CONFIG_TOUCHSCREEN_FTS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_INPUT_MPL3115=y
+CONFIG_SENSOR_FXLS8471=y
+CONFIG_SENSOR_IMX_RPMSG=y
+CONFIG_INPUT_ISL29023=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_SERIAL_DEV_BUS=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_I2C_IMX_LPI2C=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_LPSPI=y
+CONFIG_SPI_FSL_QUADSPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_FSL_DSPI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SPI_SLAVE=y
+CONFIG_SPI_SLAVE_TIME=y
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SIOX=m
+CONFIG_GPIO_IMX_RPMSG=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCF857X=y
+CONFIG_GPIO_STMPE=y
+CONFIG_GPIO_74X164=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SABRESD_MAX8903=y
+CONFIG_SENSORS_MC13783_ADC=y
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_MAX17135=y
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_STATISTICS=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_DA9063_WATCHDOG=m
+CONFIG_DA9062_WATCHDOG=y
+CONFIG_RN5T618_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_IMX7ULP_WDT=y
+CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_DA9062=y
+CONFIG_MFD_DA9063=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_MAX17135=y
+CONFIG_MFD_RN5T618=y
+CONFIG_MFD_SI476X_CORE=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_DA9062=y
+CONFIG_REGULATOR_DA9063=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX17135=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_REGULATOR_PF1550_RPMSG=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_REGULATOR_RN5T618=y
+CONFIG_RC_CORE=y
+CONFIG_RC_DEVICES=y
+CONFIG_IR_GPIO_CIR=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MUX=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_MIPI_CSI=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5640_V2=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_CAMERA_OV5640_MIPI_V2=m
+CONFIG_MXC_TVIN_ADV7180=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CODA=m
+CONFIG_VIDEO_IMX_PXP=y
+CONFIG_RADIO_SI476X=y
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_OV2680=m
+CONFIG_VIDEO_OV5645=m
+CONFIG_DRM=y
+CONFIG_DRM_MSM=y
+CONFIG_DRM_PANEL_LVDS=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_OVERLAY=y
+CONFIG_FB_MXC_MIPI_DSI_NORTHWEST=y
+CONFIG_FB_MXC_ADV7535=y
+CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E=y
+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
+CONFIG_FB_MXC_RK_PANEL_RK055AHD042=y
+CONFIG_FB_MXC_RK_PANEL_RK055IQH042=y
+CONFIG_FB_MXC_MIPI_DSI_SAMSUNG=y
+CONFIG_FB_MXC_MIPI_DSI=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_FB_MXC_EINK_V2_PANEL=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_FB_MXS_SII902X=y
+CONFIG_FB_MXC_DCIC=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_WM8960=y
+CONFIG_SND_SOC_IMX_SII902X=y
+CONFIG_SND_SOC_IMX_WM8958=y
+CONFIG_SND_SOC_IMX_CS42888=y
+CONFIG_SND_SOC_IMX_WM8962=y
+CONFIG_SND_SOC_IMX_RPMSG=y
+CONFIG_SND_SOC_IMX_ES8328=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MQS=y
+CONFIG_SND_SOC_IMX_SPDIF=y
+CONFIG_SND_SOC_IMX_MC13783=y
+CONFIG_SND_SOC_IMX_SI476X=y
+CONFIG_SND_SOC_IMX_HDMI=y
+CONFIG_SND_SOC_AC97_CODEC=y
+CONFIG_SND_SOC_TLV320AIC3X=y
+CONFIG_SND_SIMPLE_CARD=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_HCD_TEST_MODE=y
+CONFIG_USB_ACM=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_FTDI_SIO=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_TEST=m
+CONFIG_USB_EHSET_TEST_FIXTURE=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_CONFIGFS=y
+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_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=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_TRIGGERS=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_ISL1208=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_DA9063=y
+CONFIG_RTC_DRV_MC13XXX=y
+CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_MXC_V2=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_RTC_DRV_IMX_RPMSG=y
+CONFIG_DMADEVICES=y
+CONFIG_FSL_EDMA=y
+CONFIG_IMX_SDMA=y
+CONFIG_MXS_DMA=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_MXC_PXP_V3=y
+CONFIG_DMATEST=m
+CONFIG_STAGING=y
+CONFIG_STAGING_MEDIA=y
+CONFIG_COMMON_CLK_PWM=y
+CONFIG_MAILBOX=y
+CONFIG_IMX_MBOX=y
+CONFIG_REMOTEPROC=y
+CONFIG_IMX_REMOTEPROC=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_IMX7D_ADC=y
+CONFIG_VF610_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_FSL_FTM=y
+CONFIG_PWM_IMX27=y
+CONFIG_PWM_IMX_TPM=y
+CONFIG_PHY_MIXEL_LVDS=y
+CONFIG_PHY_MIXEL_LVDS_COMBO=y
+CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_NVMEM_VF610_OCOTP=y
+CONFIG_NVMEM_SNVS_LPGPR=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_MUX_MMIO=y
+CONFIG_SIOX=m
+CONFIG_SIOX_BUS_GPIO=m
+CONFIG_MXC_SIM=y
+CONFIG_MXC_IPU=y
+CONFIG_MXC_SIMv2=y
+CONFIG_MXC_MLB150=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_HDMI_CEC=y
+CONFIG_MXC_MIPI_CSI2=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_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_OVERLAY_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_POSIX_ACL=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=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_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_TLS=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+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_TGR192=m
+CONFIG_CRYPTO_WP512=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_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_SAHARA=y
+CONFIG_CRYPTO_DEV_MXS_DCP=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_STREEBOG=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_DMA_CMA=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/arm/configs/lsdk.config b/arch/arm/configs/lsdk.config
new file mode 100644
index 000000000000..0a21b724367b
--- /dev/null
+++ b/arch/arm/configs/lsdk.config
@@ -0,0 +1,88 @@
+# general
+CONFIG_ARM_MODULE_PLTS=y
+CONFIG_CHECKPOINT_RESTORE=y
+
+# virtualization
+CONFIG_KVM=y
+CONFIG_KVM_ARM_MAX_VCPUS=8
+CONFIG_VHOST_NET=y
+CONFIG_BRIDGE=y
+CONFIG_TUN=y
+
+# containers
+CONFIG_UNIX_DIAG=y
+CONFIG_PACKET_DIAG=y
+CONFIG_NETLINK_DIAG=y
+CONFIG_OVERLAY_FS=y
+
+# network and misc
+CONFIG_INET_ESP=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_VETH=y
+CONFIG_NETFILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_NF_NAT_IPV6=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_TARGET_MASQUERADE=y
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
+CONFIG_MACVLAN=y
+CONFIG_MACVTAP=y
+CONFIG_VLAN_8021Q=y
+
+# namespaces
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+
+# cgroups
+CONFIG_CPUSETS=y
+CGROUP_DEVICE=y
+CGROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_MEMCG=y
+CONFIG_CGROUP_FREEZER=y
+
+# iptables
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_IP_VS=y
+CONFIG_NETFILTER_XT_MATCH_IPVS=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_NAT=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_MASQUERADE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+
+# filesystems
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FUSE_FS=y
+
+# /proc/config.gz
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+
+# disable unneeded options and override default options set by defconfig to deduce the size of modules
+# CONFIG_DRM_TEGRA is not set
+# CONFIG_DRM_EXYNOS is not set
+# CONFIG_DRM_MSM is not set
+# CONFIG_DRM_VC4 is not set
+# CONFIG_DRM_ROCKCHIP is not set
+# CONFIG_DRM_RCAR_DU is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+# CONFIG_TEGRA_HOST1X is not set
+# CONFIG_SND_SOC_ROCKCHIP is not set
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e4c8def9a0a5..930c662b761a 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -128,8 +128,8 @@ CONFIG_CRYPTO_AES_ARM_CE=m
CONFIG_CRYPTO_GHASH_ARM_CE=m
CONFIG_CRYPTO_CRC32_ARM_CE=m
CONFIG_CRYPTO_CHACHA20_NEON=m
-CONFIG_GCC_PLUGINS=y
-CONFIG_GCC_PLUGIN_STRUCTLEAK=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_VHOST_NET=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
@@ -174,7 +174,7 @@ CONFIG_PCI_TEGRA=y
CONFIG_PCI_RCAR_GEN2=y
CONFIG_PCIE_RCAR=y
CONFIG_PCI_DRA7XX_EP=y
-CONFIG_PCI_KEYSTONE=y
+CONFIG_PCI_LAYERSCAPE=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
@@ -186,18 +186,24 @@ CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_M25P80=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_OMAP2=y
CONFIG_MTD_NAND_OMAP_BCH=y
CONFIG_MTD_NAND_ATMEL=y
CONFIG_MTD_NAND_MARVELL=y
-CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_MTD_NAND_BRCMNAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_NAND_VF610_NFC=y
CONFIG_MTD_NAND_DAVINCI=y
CONFIG_MTD_NAND_STM32_FMC2=y
@@ -220,6 +226,7 @@ CONFIG_PCI_ENDPOINT_TEST=m
CONFIG_EEPROM_AT24=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
@@ -229,6 +236,8 @@ CONFIG_AHCI_ST=y
CONFIG_AHCI_IMX=y
CONFIG_AHCI_SUNXI=y
CONFIG_AHCI_TEGRA=y
+CONFIG_AHCI_QORIQ=y
+CONFIG_SATA_SIL24=y
CONFIG_SATA_HIGHBANK=y
CONFIG_SATA_MV=y
CONFIG_SATA_RCAR=y
@@ -244,7 +253,9 @@ CONFIG_BGMAC_BCMA=y
CONFIG_SYSTEMPORT=m
CONFIG_MACB=y
CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_FSL_XGMAC_MDIO=y
CONFIG_GIANFAR=y
+CONFIG_FSL_SDK_DPAA_ETH=y
CONFIG_HIX5HD2_GMAC=y
CONFIG_E1000E=y
CONFIG_IGB=y
@@ -260,13 +271,16 @@ CONFIG_STMMAC_ETH=y
CONFIG_DWMAC_DWC_QOS_ETH=y
CONFIG_TI_CPSW=y
CONFIG_XILINX_EMACLITE=y
+CONFIG_AQUANTIA_PHY=y
CONFIG_AT803X_PHY=y
CONFIG_BROADCOM_PHY=y
CONFIG_ICPLUS_PHY=y
CONFIG_MARVELL_PHY=y
CONFIG_MICREL_PHY=y
+CONFIG_NATIONAL_PHY=y
CONFIG_ROCKCHIP_PHY=y
CONFIG_SMSC_PHY=y
+CONFIG_VITESSE_PHY=y
CONFIG_USB_PEGASUS=y
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
@@ -467,8 +481,8 @@ CONFIG_BATTERY_BQ27XXX=m
CONFIG_AXP20X_POWER=m
CONFIG_BATTERY_MAX17040=m
CONFIG_BATTERY_MAX17042=m
-CONFIG_CHARGER_GPIO=m
CONFIG_CHARGER_CPCAP=m
+CONFIG_CHARGER_GPIO=m
CONFIG_CHARGER_MAX14577=m
CONFIG_CHARGER_MAX77693=m
CONFIG_CHARGER_MAX8997=m
@@ -491,7 +505,6 @@ CONFIG_BCM2835_THERMAL=m
CONFIG_BRCMSTB_THERMAL=m
CONFIG_ST_THERMAL_MEMMAP=y
CONFIG_UNIPHIER_THERMAL=y
-CONFIG_WATCHDOG=y
CONFIG_DA9063_WATCHDOG=m
CONFIG_XILINX_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
@@ -525,10 +538,6 @@ CONFIG_MFD_BCM590XX=y
CONFIG_MFD_AC100=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_AXP20X_RSB=y
-CONFIG_MFD_CROS_EC=m
-CONFIG_CROS_EC_I2C=m
-CONFIG_CROS_EC_SPI=m
-CONFIG_MFD_CROS_EC_CHARDEV=m
CONFIG_MFD_DA9063=m
CONFIG_MFD_MAX14577=y
CONFIG_MFD_MAX77686=y
@@ -628,7 +637,6 @@ CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIVID=m
CONFIG_CEC_PLATFORM_DRIVERS=y
CONFIG_VIDEO_SAMSUNG_S5P_CEC=m
-# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
CONFIG_VIDEO_ADV7180=m
CONFIG_VIDEO_ML86V7667=m
CONFIG_DRM=y
@@ -677,16 +685,17 @@ CONFIG_DRM_PL111=m
CONFIG_DRM_LIMA=m
CONFIG_DRM_PANFROST=m
CONFIG_DRM_ASPEED_GFX=m
+CONFIG_FB_ARMCLCD=y
CONFIG_FB_EFI=y
CONFIG_FB_WM8505=y
CONFIG_FB_SH_MOBILE_LCDC=y
CONFIG_FB_SIMPLE=y
-CONFIG_LCD_PLATFORM=m
CONFIG_BACKLIGHT_PWM=y
CONFIG_BACKLIGHT_AS3711=y
CONFIG_BACKLIGHT_GPIO=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
CONFIG_SOUND=m
CONFIG_SND=m
CONFIG_SND_HDA_TEGRA=m
@@ -871,6 +880,7 @@ CONFIG_RTC_DRV_S35390A=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_EM3027=y
CONFIG_RTC_DRV_S5M=m
+CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_DA9063=m
CONFIG_RTC_DRV_EFI=m
CONFIG_RTC_DRV_DIGICOLOR=m
@@ -919,6 +929,10 @@ CONFIG_SERIO_NVEC_PS2=y
CONFIG_NVEC_POWER=y
CONFIG_NVEC_PAZ00=y
CONFIG_STAGING_BOARD=y
+CONFIG_FSL_SDK_DPA=y
+CONFIG_MFD_CROS_EC=m
+CONFIG_CROS_EC_I2C=m
+CONFIG_CROS_EC_SPI=m
CONFIG_COMMON_CLK_MAX77686=y
CONFIG_COMMON_CLK_RK808=m
CONFIG_COMMON_CLK_S2MPS11=m
@@ -978,16 +992,15 @@ CONFIG_BERLIN2_ADC=m
CONFIG_CPCAP_ADC=m
CONFIG_EXYNOS_ADC=m
CONFIG_MESON_SARADC=m
+CONFIG_ROCKCHIP_SARADC=m
CONFIG_STM32_ADC_CORE=m
CONFIG_STM32_ADC=m
CONFIG_STM32_DFSDM_ADC=m
CONFIG_VF610_ADC=m
CONFIG_XILINX_XADC=y
-CONFIG_STM32_LPTIMER_CNT=m
-CONFIG_STM32_DAC=m
-CONFIG_ROCKCHIP_SARADC=m
CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
+CONFIG_STM32_DAC=m
CONFIG_MPU3050_I2C=y
CONFIG_CM36651=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
@@ -1036,11 +1049,11 @@ CONFIG_PHY_DM816X_USB=m
CONFIG_OMAP_USB2=y
CONFIG_TI_PIPE3=y
CONFIG_TWL4030_USB=m
-CONFIG_MESON_MX_EFUSE=m
-CONFIG_ROCKCHIP_EFUSE=m
CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_ROCKCHIP_EFUSE=m
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_VF610_OCOTP=y
+CONFIG_MESON_MX_EFUSE=m
CONFIG_EXT4_FS=y
CONFIG_AUTOFS4_FS=y
CONFIG_MSDOS_FS=y
@@ -1068,6 +1081,7 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_DEV_MARVELL_CESA=m
+CONFIG_CRYPTO_DEV_FSL_CAAM=m
CONFIG_CRYPTO_DEV_EXYNOS_RNG=m
CONFIG_CRYPTO_DEV_S5P=m
CONFIG_CRYPTO_DEV_ATMEL_AES=m
diff --git a/arch/arm/configs/multi_v7_lpae.config b/arch/arm/configs/multi_v7_lpae.config
new file mode 100644
index 000000000000..cd13d2df5fd5
--- /dev/null
+++ b/arch/arm/configs/multi_v7_lpae.config
@@ -0,0 +1,2 @@
+# Support for the Large Physical Address Extension
+CONFIG_ARM_LPAE=y
diff --git a/arch/arm/configs/multi_v8.config b/arch/arm/configs/multi_v8.config
new file mode 100644
index 000000000000..2203dabebc44
--- /dev/null
+++ b/arch/arm/configs/multi_v8.config
@@ -0,0 +1,23 @@
+# ppfe
+CONFIG_FSL_PPFE=y
+CONFIG_FSL_PPFE_UTIL_DISABLED=y
+# DPAA 1
+CONFIG_HAS_FSL_QBMAN=y
+# network
+CONFIG_BRIDGE=m
+CONFIG_MACVLAN=y
+CONFIG_FSL_SDK_FMAN=y
+CONFIG_FMAN_ARM=y
+CONFIG_FSL_SDK_DPAA_ETH=y
+# mdio
+CONFIG_FSL_XGMAC_MDIO=y
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
+# phy
+CONFIG_AQUANTIA_PHY=y
+CONFIG_VITESSE_PHY=y
+# NVMe
+CONFIG_BLK_DEV_NVME=y
+# vfio
+CONFIG_VFIO=y
+CONFIG_VFIO_PCI=y
+CONFIG_VFIO_FSL_MC=y
diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
index 4f80b72372b4..f1aebe735321 100644
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -85,6 +85,22 @@ extern void __bad_udelay(void);
__const_udelay((n) * UDELAY_MULT)) : \
__udelay(n))
+#define spin_event_timeout(condition, timeout, delay) \
+({ \
+ typeof(condition) __ret; \
+ int i = 0; \
+ while (!(__ret = (condition)) && (i++ < timeout)) { \
+ if (delay) \
+ udelay(delay); \
+ else \
+ cpu_relax(); \
+ udelay(1); \
+ } \
+ if (!__ret) \
+ __ret = (condition); \
+ __ret; \
+})
+
/* Loop-based definitions for assembly code. */
extern void __loop_delay(unsigned long loops);
extern void __loop_udelay(unsigned long usecs);
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 7a0596fcb2e7..b026d499e42d 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -123,6 +123,7 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
#define MT_DEVICE_NONSHARED 1
#define MT_DEVICE_CACHED 2
#define MT_DEVICE_WC 3
+#define MT_MEMORY_RW_NS 4
/*
* types 4 onwards can be found in asm/mach/map.h and are undefined
* for ioremap
@@ -224,6 +225,34 @@ void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size);
#endif
#endif
+/* access ports */
+#define setbits32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr))
+#define clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr))
+
+#define setbits16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr))
+#define clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr))
+
+#define setbits8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr))
+#define clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr))
+
+/* Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single read-modify-write. These
+ * macros can also be used to set a multiple-bit bit pattern using a mask,
+ * by specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrsetbits_be32(addr, clear, set) \
+ iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_le32(addr, clear, set) \
+ iowrite32le((ioread32le(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_be16(addr, clear, set) \
+ iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_le16(addr, clear, set) \
+ iowrite16le((ioread16le(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_8(addr, clear, set) \
+ iowrite8((ioread8(addr) & ~(clear)) | (set), (addr))
+
/*
* IO port access primitives
* -------------------------
@@ -410,6 +439,8 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
#define ioremap_wc ioremap_wc
#define ioremap_wt ioremap_wc
+void __iomem *ioremap_cache_ns(resource_size_t res_cookie, size_t size);
+
void iounmap(volatile void __iomem *iomem_cookie);
#define iounmap iounmap
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 0d84d50bf9ba..d18f3ef33633 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -55,7 +55,8 @@ void stage2_unmap_vm(struct kvm *kvm);
int kvm_alloc_stage2_pgd(struct kvm *kvm);
void kvm_free_stage2_pgd(struct kvm *kvm);
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
- phys_addr_t pa, unsigned long size, bool writable);
+ phys_addr_t pa, unsigned long size, bool writable,
+ pgprot_t prot);
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index 92282558caf7..05e1af2179f9 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -18,9 +18,9 @@ struct map_desc {
unsigned int type;
};
-/* types 0-3 are defined in asm/io.h */
+/* types 0-4 are defined in asm/io.h */
enum {
- MT_UNCACHED = 4,
+ MT_UNCACHED = 5,
MT_CACHECLEAN,
MT_MINICLEAN,
MT_LOW_VECTORS,
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 3ae120cd1715..ea5c29c11bc8 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -116,6 +116,13 @@ extern pgprot_t pgprot_s2_device;
#define pgprot_noncached(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+#define pgprot_cached(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_CACHED)
+
+#define pgprot_cached_ns(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_CACHED | \
+ L_PTE_MT_DEV_NONSHARED)
+
#define pgprot_writecombine(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index ed46ca69813d..cc9e5b3cdbcf 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -12,11 +12,14 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/of_irq.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/mach/pci.h>
+#include "../../../drivers/pci/pcie/portdrv.h"
+
static int debug_pci;
/*
@@ -65,6 +68,47 @@ void pcibios_report_status(u_int status_mask, int warn)
}
/*
+ * Check device tree if the service interrupts are there
+ */
+int pcibios_check_service_irqs(struct pci_dev *dev, int *irqs, int mask)
+{
+ int ret, count = 0;
+ struct device_node *np = NULL;
+
+ if (dev->bus->dev.of_node)
+ np = dev->bus->dev.of_node;
+
+ if (np == NULL)
+ return 0;
+
+ if (!IS_ENABLED(CONFIG_OF_IRQ))
+ return 0;
+
+ /* If root port doesn't support MSI/MSI-X/INTx in RC mode,
+ * request irq for aer
+ */
+ if (mask & PCIE_PORT_SERVICE_AER) {
+ ret = of_irq_get_byname(np, "aer");
+ if (ret > 0) {
+ irqs[PCIE_PORT_SERVICE_AER_SHIFT] = ret;
+ count++;
+ }
+ }
+
+ if (mask & PCIE_PORT_SERVICE_PME) {
+ ret = of_irq_get_byname(np, "pme");
+ if (ret > 0) {
+ irqs[PCIE_PORT_SERVICE_PME_SHIFT] = ret;
+ count++;
+ }
+ }
+
+ /* TODO: add more service interrupts if there it is in the device tree*/
+
+ return count;
+}
+
+/*
* We don't use this to fix the device, but initialisation of it.
* It's not the correct use for this, but it works.
* Note that the arbiter/ISA bridge appears to be buggy, specifically in
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b996b2cf0703..a148421cf482 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -9,6 +9,7 @@
* reading the RTC at bootup, etc...
*/
#include <linux/clk-provider.h>
+#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/errno.h>
#include <linux/export.h>
@@ -107,5 +108,7 @@ void __init time_init(void)
of_clk_init(NULL);
#endif
timer_probe();
+
+ tick_setup_hrtimer_broadcast();
}
}
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 95584ee02b55..b80a060a0a7f 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -40,9 +40,29 @@ config HAVE_IMX_GPC
bool
select PM_GENERIC_DOMAINS if PM
+config HAVE_IMX_GPCV2
+ bool
+ select PM_GENERIC_DOMAINS if PM
+
config HAVE_IMX_MMDC
bool
+config HAVE_IMX_AMP
+ bool
+
+config HAVE_IMX_DDRC
+ bool
+ select HAVE_IMX_BUSFREQ
+
+config HAVE_IMX_BUSFREQ
+ bool
+
+config HAVE_IMX_MU
+ bool
+
+config HAVE_IMX_RPMSG
+ bool
+
config HAVE_IMX_SRC
def_bool y if SMP
select ARCH_HAS_RESET_CONTROLLER
@@ -475,6 +495,7 @@ config SOC_IMX6
select ARM_ERRATA_775420
select ARM_GIC
select HAVE_IMX_ANATOP
+ select HAVE_IMX_BUSFREQ
select HAVE_IMX_GPC
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
@@ -511,7 +532,12 @@ config SOC_IMX6SLL
config SOC_IMX6SX
bool "i.MX6 SoloX support"
select PINCTRL_IMX6SX
+ select HAVE_IMX_AMP
select SOC_IMX6
+ select HAVE_IMX_MU
+ select HAVE_IMX_RPMSG
+ select IMX_SEMA4
+ select KEYBOARD_SNVS_PWRKEY
help
This enables support for Freescale i.MX6 SoloX processor.
@@ -547,6 +573,11 @@ config SOC_IMX7D_CA7
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select IMX_GPCV2
+ select HAVE_IMX_DDRC
+ select HAVE_IMX_MU
+ select HAVE_IMX_RPMSG
+ select HAVE_IMX_GPCV2
+ select KEYBOARD_SNVS_PWRKEY
config SOC_IMX7D_CM4
bool
@@ -557,7 +588,7 @@ config SOC_IMX7D
select PINCTRL_IMX7D
select SOC_IMX7D_CA7 if ARCH_MULTI_V7
select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
- select ARM_ERRATA_814220 if ARCH_MULTI_V7
+ select ARM_ERRATA_814220
help
This enables support for Freescale i.MX7 Dual processor.
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e7364e6c8c6b..e4cd47d2a144 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y := cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o common.o
obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
@@ -25,11 +25,18 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
-obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
-obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sx.o
-obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
-obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6sx.o
-obj-$(CONFIG_SOC_IMX7ULP) += cpuidle-imx7ulp.o
+AFLAGS_imx6sl_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o imx6sl_low_power_idle.o
+AFLAGS_imx6sll_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sll.o imx6sll_low_power_idle.o
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o imx6sx_low_power_idle.o
+AFLAGS_imx6sx_low_power_idle.o :=-Wa,-march=armv7-a
+AFLAGS_imx6ul_low_power_idle.o :=-Wa,-march=armv7-a
+AFLAGS_imx6ull_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6ul.o imx6ul_low_power_idle.o imx6ull_low_power_idle.o
+obj-$(CONFIG_SOC_IMX7ULP) += cpuidle-imx7ulp.o pm-rpmsg.o
+AFLAGS_imx7d_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX7D_CA7) += cpuidle-imx7d.o imx7d_low_power_idle.o
endif
ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
@@ -70,26 +77,46 @@ obj-$(CONFIG_MACH_IMX35_DT) += imx35-dt.o
obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_HAVE_IMX_GPCV2) += gpcv2.o
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),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
-obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
-obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
-obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o
-obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
-obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
-obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o
+obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o ddr3_freq_imx6.o smp_wfe_imx6.o \
+ lpddr2_freq_imx6q.o
+obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o lpddr2_freq_imx6.o
+obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o lpddr2_freq_imx6sll.o
+obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o ddr3_freq_imx6sx.o lpddr2_freq_imx6sx.o
+obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o ddr3_freq_imx6sx.o lpddr2_freq_imx6sx.o
+obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o pm-imx7.o ddr3_freq_imx7d.o smp_wfe.o \
+ lpddr3_freq_imx.o suspend-imx7.o
obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
obj-$(CONFIG_SOC_IMX7ULP) += mach-imx7ulp.o pm-imx7ulp.o
+obj-$(CONFIG_HAVE_IMX_BUSFREQ) += busfreq-imx.o busfreq_ddr3.o busfreq_lpddr2.o
+AFLAGS_smp_wfe.o :=-Wa,-march=armv7-a
+AFLAGS_smp_wfe_imx6.o :=-Wa,-march=armv7-a
+AFLAGS_ddr3_freq_imx7d.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr3_freq_imx.o :=-Wa,-march=armv7-a
+AFLAGS_ddr3_freq_imx6.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6q.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6sx.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6sll.o :=-Wa,-march=armv7-a
+AFLAGS_ddr3_freq_imx6sx.o :=-Wa,-march=armv7-a
+
ifeq ($(CONFIG_SUSPEND),y)
AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
+AFLAGS_suspend-imx7.o :=-Wa,-march=armv7-a
+AFLAGS_suspend-imx7ulp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
+obj-$(CONFIG_SOC_IMX7ULP) += suspend-imx7ulp.o
endif
ifeq ($(CONFIG_ARM_CPU_SUSPEND),y)
AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index 777d8c255501..a9ec0159b8f0 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -4,6 +4,7 @@
* Copyright 2017-2018 NXP.
*/
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -16,38 +17,63 @@
#define REG_SET 0x4
#define REG_CLR 0x8
+#define ANADIG_ARM_PLL 0x60
+#define ANADIG_DDR_PLL 0x70
+#define ANADIG_SYS_PLL 0xb0
+#define ANADIG_ENET_PLL 0xe0
+#define ANADIG_AUDIO_PLL 0xf0
+#define ANADIG_VIDEO_PLL 0x130
+
#define ANADIG_REG_2P5 0x130
#define ANADIG_REG_CORE 0x140
#define ANADIG_ANA_MISC0 0x150
#define ANADIG_USB1_CHRG_DETECT 0x1b0
#define ANADIG_USB2_CHRG_DETECT 0x210
+#define ANADIG_ANA_MISC2 0x170
#define ANADIG_DIGPROG 0x260
#define ANADIG_DIGPROG_IMX6SL 0x280
#define ANADIG_DIGPROG_IMX7D 0x800
-#define SRC_SBMR2 0x1c
-
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8
#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
+#define BM_ANADIG_REG_CORE_REG1 (0x1f << 9)
+#define BM_ANADIG_REG_CORE_REG2 (0x1f << 18)
+#define BP_ANADIG_REG_CORE_REG2 (18)
#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
+#define BM_ANADIG_ANA_MISC0_V2_STOP_MODE_CONFIG 0x800
+#define BM_ANADIG_ANA_MISC0_V3_STOP_MODE_CONFIG 0xc00
+#define BM_ANADIG_ANA_MISC2_REG1_STEP_TIME (0x3 << 26)
+#define BP_ANADIG_ANA_MISC2_REG1_STEP_TIME (26)
/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS 0x2000
+/* Since i.MX6SX, DISCON_HIGH_SNVS is changed to bit 12 */
+#define BM_ANADIG_ANA_MISC0_V2_DISCON_HIGH_SNVS 0x1000
#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
+#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
+#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
+
static struct regmap *anatop;
static void imx_anatop_enable_weak2p5(bool enable)
{
- u32 reg, val;
+ u32 reg, val, mask;
regmap_read(anatop, ANADIG_ANA_MISC0, &val);
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ mask = BM_ANADIG_ANA_MISC0_V3_STOP_MODE_CONFIG;
+ else if (cpu_is_imx6sl())
+ mask = BM_ANADIG_ANA_MISC0_V2_STOP_MODE_CONFIG;
+ else
+ mask = BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG;
+
/* can only be enabled when stop_mode_config is clear. */
reg = ANADIG_REG_2P5;
- reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
- REG_SET : REG_CLR;
+ reg += (enable && (val & mask) == 0) ? REG_SET : REG_CLR;
regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
}
@@ -65,35 +91,89 @@ static inline void imx_anatop_enable_2p5_pulldown(bool enable)
static inline void imx_anatop_disconnect_high_snvs(bool enable)
{
- regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
- BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ regmap_write(anatop, ANADIG_ANA_MISC0 +
+ (enable ? REG_SET : REG_CLR),
+ BM_ANADIG_ANA_MISC0_V2_DISCON_HIGH_SNVS);
+ else
+ regmap_write(anatop, ANADIG_ANA_MISC0 +
+ (enable ? REG_SET : REG_CLR),
+ BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
+}
+
+static void imx_anatop_disable_pu(bool off)
+{
+ u32 val, soc, delay;
+ if (off) {
+ regmap_read(anatop, ANADIG_REG_CORE, &val);
+ val &= ~BM_ANADIG_REG_CORE_REG1;
+ regmap_write(anatop, ANADIG_REG_CORE, val);
+ } else {
+ /* track vddpu with vddsoc */
+ regmap_read(anatop, ANADIG_REG_CORE, &val);
+ soc = val & BM_ANADIG_REG_CORE_REG2;
+ val &= ~BM_ANADIG_REG_CORE_REG1;
+ val |= soc >> 9;
+ regmap_write(anatop, ANADIG_REG_CORE, val);
+ /* wait PU LDO ramp */
+ regmap_read(anatop, ANADIG_ANA_MISC2, &val);
+ val &= BM_ANADIG_ANA_MISC2_REG1_STEP_TIME;
+ val >>= BP_ANADIG_ANA_MISC2_REG1_STEP_TIME;
+ delay = (soc >> BP_ANADIG_REG_CORE_REG2) *
+ (LDO_RAMP_UP_UNIT_IN_CYCLES << val) /
+ LDO_RAMP_UP_FREQ_IN_MHZ + 1;
+ udelay(delay);
+ }
}
void imx_anatop_pre_suspend(void)
{
- if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
- imx_anatop_enable_2p5_pulldown(true);
- else
- imx_anatop_enable_weak2p5(true);
+ if (cpu_is_imx7d()) {
+ /* PLL and PFDs overwrite set */
+ regmap_write(anatop, ANADIG_ARM_PLL + REG_SET, 1 << 20);
+ regmap_write(anatop, ANADIG_DDR_PLL + REG_SET, 1 << 19);
+ regmap_write(anatop, ANADIG_SYS_PLL + REG_SET, 0x1ff << 17);
+ regmap_write(anatop, ANADIG_ENET_PLL + REG_SET, 1 << 13);
+ regmap_write(anatop, ANADIG_AUDIO_PLL + REG_SET, 1 << 24);
+ regmap_write(anatop, ANADIG_VIDEO_PLL + REG_SET, 1 << 24);
+ return;
+ }
+
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ imx_anatop_disable_pu(true);
+ imx_anatop_enable_weak2p5(true);
imx_anatop_enable_fet_odrive(true);
- if (cpu_is_imx6sl())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
+ cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
imx_anatop_disconnect_high_snvs(true);
}
void imx_anatop_post_resume(void)
{
- if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
- imx_anatop_enable_2p5_pulldown(false);
- else
- imx_anatop_enable_weak2p5(false);
+ if (cpu_is_imx7d()) {
+ /* PLL and PFDs overwrite clear */
+ regmap_write(anatop, ANADIG_ARM_PLL + REG_CLR, 1 << 20);
+ regmap_write(anatop, ANADIG_DDR_PLL + REG_CLR, 1 << 19);
+ regmap_write(anatop, ANADIG_SYS_PLL + REG_CLR, 0x1ff << 17);
+ regmap_write(anatop, ANADIG_ENET_PLL + REG_CLR, 1 << 13);
+ regmap_write(anatop, ANADIG_AUDIO_PLL + REG_CLR, 1 << 24);
+ regmap_write(anatop, ANADIG_VIDEO_PLL + REG_CLR, 1 << 24);
+ return;
+ }
+
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ imx_anatop_disable_pu(false);
+
+ imx_anatop_enable_weak2p5(false);
imx_anatop_enable_fet_odrive(false);
- if (cpu_is_imx6sl())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
+ cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
imx_anatop_disconnect_high_snvs(false);
-
}
static void imx_anatop_usb_chrg_detect_disable(void)
@@ -110,10 +190,11 @@ void __init imx_init_revision_from_anatop(void)
{
struct device_node *np;
void __iomem *anatop_base;
+ void __iomem *src_base;
unsigned int revision;
- u32 digprog;
+ u32 digprog, sbmr2 = 0;
u16 offset = ANADIG_DIGPROG;
- u8 major_part, minor_part;
+ u16 major_part, minor_part;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
anatop_base = of_iomap(np, 0);
@@ -125,6 +206,20 @@ void __init imx_init_revision_from_anatop(void)
digprog = readl_relaxed(anatop_base + offset);
iounmap(anatop_base);
+ if ((digprog >> 16) == MXC_CPU_IMX6ULL) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-src");
+ if (np) {
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+ sbmr2 = readl_relaxed(src_base + 0x1c);
+ iounmap(src_base);
+ }
+ if (sbmr2 & (1 << 6)) {
+ digprog &= ~(0xff << 16);
+ digprog |= (MXC_CPU_IMX6ULZ << 16);
+ }
+ }
+
/*
* On i.MX7D digprog value match linux version format, so
* it needn't map again and we can use register value directly.
@@ -144,24 +239,6 @@ void __init imx_init_revision_from_anatop(void)
major_part = (digprog >> 8) & 0xf;
minor_part = digprog & 0xf;
revision = ((major_part + 1) << 4) | minor_part;
-
- if ((digprog >> 16) == MXC_CPU_IMX6ULL) {
- void __iomem *src_base;
- u32 sbmr2;
-
- np = of_find_compatible_node(NULL, NULL,
- "fsl,imx6ul-src");
- src_base = of_iomap(np, 0);
- WARN_ON(!src_base);
- sbmr2 = readl_relaxed(src_base + SRC_SBMR2);
- iounmap(src_base);
-
- /* src_sbmr2 bit 6 is to identify if it is i.MX6ULZ */
- if (sbmr2 & (1 << 6)) {
- digprog &= ~(0xff << 16);
- digprog |= (MXC_CPU_IMX6ULZ << 16);
- }
- }
}
mxc_set_cpu_type(digprog >> 16 & 0xff);
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
new file mode 100644
index 000000000000..026f9a8090ae
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -0,0 +1,1407 @@
+/*
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP.
+ * Copyright 2018 NXP.
+ *
+ * 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 <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/tlb.h>
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+#include "hardware.h"
+#include "common.h"
+
+#define LPAPM_CLK 24000000
+#define LOW_AUDIO_CLK 50000000
+#define HIGH_AUDIO_CLK 100000000
+
+#define LOW_POWER_RUN_VOLTAGE 950000
+
+#define MMDC_MDMISC_DDR_TYPE_DDR3 0
+#define MMDC_MDMISC_DDR_TYPE_LPDDR2 1
+
+unsigned int ddr_med_rate;
+unsigned int ddr_normal_rate;
+unsigned long ddr_freq_change_total_size;
+unsigned long ddr_freq_change_iram_base;
+unsigned long ddr_freq_change_iram_phys;
+
+static int ddr_type;
+static int low_bus_freq_mode;
+static int audio_bus_freq_mode;
+static int ultra_low_bus_freq_mode;
+static int high_bus_freq_mode;
+static int med_bus_freq_mode;
+static int bus_freq_scaling_initialized;
+static bool cancel_reduce_bus_freq;
+static struct device *busfreq_dev;
+static int busfreq_suspended;
+static int bus_freq_scaling_is_active;
+static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count;
+static unsigned int ddr_low_rate;
+static int cur_bus_freq_mode;
+static u32 org_arm_rate;
+
+extern unsigned long iram_tlb_phys_addr;
+extern int unsigned long iram_tlb_base_addr;
+
+/*
+ * Bus frequency management by Linux
+ */
+extern int init_mmdc_lpddr2_settings(struct platform_device *dev);
+extern int init_mmdc_lpddr2_settings_mx6q(struct platform_device *dev);
+extern int init_mmdc_ddr3_settings_imx6_up(struct platform_device *dev);
+extern int init_mmdc_ddr3_settings_imx6_smp(struct platform_device *dev);
+extern int init_ddrc_ddr_settings(struct platform_device *dev);
+extern int update_ddr_freq_imx_smp(int ddr_rate);
+extern int update_ddr_freq_imx6_up(int ddr_rate);
+extern int update_lpddr2_freq(int ddr_rate);
+extern int update_lpddr2_freq_smp(int ddr_rate);
+
+
+/**
+ * @brief Functions to init and update the busfreq function of
+ * device and memory type
+ */
+static struct busfreq_func {
+ int (*init)(struct platform_device *dev);
+ int (*update)(int ddr_rate);
+} busfreq_func = {NULL, NULL};
+
+DEFINE_MUTEX(bus_freq_mutex);
+
+static struct clk *osc_clk;
+static struct clk *ahb_clk;
+static struct clk *axi_sel_clk;
+static struct clk *dram_root;
+static struct clk *dram_alt_sel;
+static struct clk *dram_alt_root;
+static struct clk *pfd0_392m;
+static struct clk *pfd2_270m;
+static struct clk *pfd1_332m;
+static struct clk *pll_dram;
+static struct clk *ahb_sel_clk;
+static struct clk *axi_clk;
+
+static struct clk *m4_clk;
+static struct clk *pll3_clk;
+static struct clk *pll2_400_clk;
+static struct clk *periph_clk2_sel_clk;
+static struct clk *periph_pre_clk;
+static struct clk *pll2_200_clk;
+static struct clk *periph_clk;
+static struct clk *mmdc_clk;
+static struct clk *periph_clk2_clk;
+static struct clk *pll2_bus_clk;
+
+static struct clk *pll2_bypass_src_clk;
+static struct clk *pll2_bypass_clk;
+static struct clk *pll2_clk;
+static struct clk *arm_clk;
+static struct clk *step_clk;
+static struct clk *pll1_clk;
+static struct clk *pll1_bypass_src_clk;
+static struct clk *pll1_bypass_clk;
+static struct clk *pll1_sys_clk;
+static struct clk *pll1_sw_clk;
+
+static struct clk *axi_alt_sel_clk;
+static struct clk *pll3_pfd1_540m_clk;
+
+static struct clk *ocram_clk;
+static struct clk *periph2_clk;
+static struct clk *periph2_pre_clk;
+static struct clk *periph2_clk2_clk;
+static struct clk *periph2_clk2_sel_clk;
+
+static struct delayed_work low_bus_freq_handler;
+static struct delayed_work bus_freq_daemon;
+
+static RAW_NOTIFIER_HEAD(busfreq_notifier_chain);
+
+static bool check_m4_sleep(void)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+ while (imx_gpc_is_m4_sleeping() == 0)
+ if (time_after(jiffies, timeout))
+ return false;
+ return true;
+}
+
+static bool busfreq_notified_low = false;
+
+static int busfreq_notify(enum busfreq_event event)
+{
+ int ret;
+
+ if (event == LOW_BUSFREQ_ENTER) {
+ WARN_ON(busfreq_notified_low);
+ busfreq_notified_low = true;
+ } else if (event == LOW_BUSFREQ_EXIT) {
+ WARN_ON(!busfreq_notified_low);
+ busfreq_notified_low = false;
+ }
+ ret = raw_notifier_call_chain(&busfreq_notifier_chain, event, NULL);
+
+ return notifier_to_errno(ret);
+}
+
+int register_busfreq_notifier(struct notifier_block *nb)
+{
+ return raw_notifier_chain_register(&busfreq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(register_busfreq_notifier);
+
+int unregister_busfreq_notifier(struct notifier_block *nb)
+{
+ return raw_notifier_chain_unregister(&busfreq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(unregister_busfreq_notifier);
+
+static struct clk *origin_step_parent;
+
+/*
+ * on i.MX6ULL, when entering low bus mode, the ARM core
+ * can run at 24MHz to support the low power run mode per
+ * to design team.
+ */
+static void imx6ull_lower_cpu_rate(bool enter)
+{
+ if (enter) {
+ org_arm_rate = clk_get_rate(arm_clk);
+ }
+
+ clk_set_parent(pll1_bypass_clk, pll1_bypass_src_clk);
+ clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+
+ if (enter) {
+ origin_step_parent = clk_get_parent(step_clk);
+ clk_set_parent(step_clk, osc_clk);
+ clk_set_parent(pll1_sw_clk, step_clk);
+ clk_set_rate(arm_clk, LPAPM_CLK);
+ } else {
+ clk_set_parent(step_clk, origin_step_parent);
+ clk_set_parent(pll1_sw_clk, step_clk);
+ clk_set_rate(arm_clk, org_arm_rate);
+ clk_set_parent(pll1_bypass_clk, pll1_clk);
+ }
+}
+
+/*
+ * enter_lpm_imx6_up and exit_lpm_imx6_up is used by
+ * i.MX6SX/i.MX6UL for entering and exiting lpm mode.
+ */
+static void enter_lpm_imx6_up(void)
+{
+ if (cpu_is_imx6sx() && imx_src_is_m4_enabled())
+ if (!check_m4_sleep())
+ pr_err("M4 is NOT in sleep!!!\n");
+
+ /* set periph_clk2 to source from OSC for periph */
+ clk_set_parent(periph_clk2_sel_clk, osc_clk);
+ clk_set_parent(periph_clk, periph_clk2_clk);
+ /* set ahb/ocram to 24MHz */
+ clk_set_rate(ahb_clk, LPAPM_CLK);
+ clk_set_rate(ocram_clk, LPAPM_CLK);
+
+ if (audio_bus_count) {
+ /* Need to ensure that PLL2_PFD_400M is kept ON. */
+ clk_prepare_enable(pll2_400_clk);
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ busfreq_func.update(LOW_AUDIO_CLK);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ busfreq_func.update(HIGH_AUDIO_CLK);
+ clk_set_parent(periph2_clk2_sel_clk, pll3_clk);
+ clk_set_parent(periph2_pre_clk, pll2_400_clk);
+ clk_set_parent(periph2_clk, periph2_pre_clk);
+ /*
+ * As periph2_clk's parent is not changed from
+ * high mode to audio mode, so clk framework
+ * will not update its children's freq, but we
+ * change the mmdc's podf in asm code, so here
+ * need to update mmdc rate to make sure clk
+ * tree is right, although it will not do any
+ * change to hardware.
+ */
+ if (high_bus_freq_mode) {
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ clk_set_rate(mmdc_clk, LOW_AUDIO_CLK);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ clk_set_rate(mmdc_clk, HIGH_AUDIO_CLK);
+ }
+
+ if ((cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) && low_bus_freq_mode)
+ imx6ull_lower_cpu_rate(false);
+
+ audio_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_AUDIO;
+ } else {
+ busfreq_func.update(LPAPM_CLK);
+
+ clk_set_parent(periph2_clk2_sel_clk, osc_clk);
+ clk_set_parent(periph2_clk, periph2_clk2_clk);
+
+ if (audio_bus_freq_mode)
+ clk_disable_unprepare(pll2_400_clk);
+
+ if (cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
+ imx6ull_lower_cpu_rate(true);
+
+ low_bus_freq_mode = 1;
+ audio_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_LOW;
+ }
+}
+
+static void enter_lpm_imx6_smp(void)
+{
+ if (cpu_is_imx6dl())
+ /* Set axi to periph_clk */
+ clk_set_parent(axi_sel_clk, periph_clk);
+
+ if (audio_bus_count) {
+ /* Need to ensure that PLL2_PFD_400M is kept ON. */
+ clk_prepare_enable(pll2_400_clk);
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ busfreq_func.update(LOW_AUDIO_CLK);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ busfreq_func.update(HIGH_AUDIO_CLK);
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk2_sel_clk, pll3_clk);
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ clk_set_parent(periph_pre_clk, pll2_200_clk);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ clk_set_parent(periph_pre_clk, pll2_400_clk);
+ clk_set_parent(periph_clk, periph_pre_clk);
+
+ /*
+ * As periph_pre_clk's parent is not changed from
+ * high mode to audio mode on lpddr2, the clk framework
+ * will not update its children's freq, but we
+ * change the mmdc_ch0_axi podf in asm code, so here
+ * need to update mmdc rate to make sure clk
+ * tree is right, although it will not do any
+ * change to hardware. Calling get_rate will only call
+ * the .rate_recalc which is all we need.
+ */
+ if (high_bus_freq_mode && mmdc_clk)
+ if (ddr_type == IMX_DDR_TYPE_LPDDR2)
+ clk_get_rate(mmdc_clk);
+
+ audio_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_AUDIO;
+ } else {
+ busfreq_func.update(LPAPM_CLK);
+
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk2_sel_clk, osc_clk);
+ /* Set periph_clk parent to OSC via periph_clk2_sel */
+ clk_set_parent(periph_clk, periph_clk2_clk);
+ if (audio_bus_freq_mode)
+ clk_disable_unprepare(pll2_400_clk);
+ low_bus_freq_mode = 1;
+ audio_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_LOW;
+ }
+}
+
+static void exit_lpm_imx6_up(void)
+{
+ if ((cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) && low_bus_freq_mode)
+ imx6ull_lower_cpu_rate(false);
+
+ clk_prepare_enable(pll2_400_clk);
+
+ /*
+ * lower ahb/ocram's freq first to avoid too high
+ * freq during parent switch from OSC to pll3.
+ */
+ if (cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz()
+ || cpu_is_imx6sll())
+ clk_set_rate(ahb_clk, LPAPM_CLK / 4);
+ else
+ clk_set_rate(ahb_clk, LPAPM_CLK / 3);
+
+ clk_set_rate(ocram_clk, LPAPM_CLK / 2);
+ /* set periph clk to from pll2_bus on i.MX6UL */
+ if (cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
+ clk_set_parent(periph_pre_clk, pll2_bus_clk);
+ /* set periph clk to from pll2_400 */
+ else
+ clk_set_parent(periph_pre_clk, pll2_400_clk);
+ clk_set_parent(periph_clk, periph_pre_clk);
+ /* set periph_clk2 to pll3 */
+ clk_set_parent(periph_clk2_sel_clk, pll3_clk);
+
+ busfreq_func.update(ddr_normal_rate);
+
+ /* correct parent info after ddr freq change in asm code */
+ clk_set_parent(periph2_pre_clk, pll2_400_clk);
+ clk_set_parent(periph2_clk, periph2_pre_clk);
+ clk_set_parent(periph2_clk2_sel_clk, pll3_clk);
+
+ /*
+ * As periph2_clk's parent is not changed from
+ * audio mode to high mode, so clk framework
+ * will not update its children's freq, but we
+ * change the mmdc's podf in asm code, so here
+ * need to update mmdc rate to make sure clk
+ * tree is right, although it will not do any
+ * change to hardware.
+ */
+ if (audio_bus_freq_mode)
+ clk_set_rate(mmdc_clk, ddr_normal_rate);
+
+ clk_disable_unprepare(pll2_400_clk);
+
+ if (audio_bus_freq_mode)
+ clk_disable_unprepare(pll2_400_clk);
+}
+
+static void exit_lpm_imx6_smp(void)
+{
+ struct clk *periph_clk_parent;
+
+ if (cpu_is_imx6q() && ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ periph_clk_parent = pll2_bus_clk;
+ else
+ periph_clk_parent = pll2_400_clk;
+
+ clk_prepare_enable(pll2_400_clk);
+
+ busfreq_func.update(ddr_normal_rate);
+
+ /* Make sure periph clk's parent also got updated */
+ clk_set_parent(periph_clk2_sel_clk, pll3_clk);
+ clk_set_parent(periph_pre_clk, periph_clk_parent);
+ clk_set_parent(periph_clk, periph_pre_clk);
+ if (cpu_is_imx6dl()) {
+ /* Set axi to pll3_pfd1_540m */
+ clk_set_parent(axi_alt_sel_clk, pll3_pfd1_540m_clk);
+ clk_set_parent(axi_sel_clk, axi_alt_sel_clk);
+ }
+ /*
+ * As periph_pre_clk's parent is not changed from
+ * high mode to audio mode on lpddr2, the clk framework
+ * will not update its children's freq, but we
+ * change the mmdc_ch0_axi podf in asm code, so here
+ * need to update mmdc rate to make sure clk
+ * tree is right, although it will not do any
+ * change to hardware. Calling get_rate will only call
+ * the .rate_recalc which is all we need.
+ */
+ if (audio_bus_freq_mode && mmdc_clk)
+ if (ddr_type == IMX_DDR_TYPE_LPDDR2)
+ clk_get_rate(mmdc_clk);
+
+ clk_disable_unprepare(pll2_400_clk);
+ if (audio_bus_freq_mode)
+ clk_disable_unprepare(pll2_400_clk);
+}
+
+static void enter_lpm_imx6sl(void)
+{
+ if (high_bus_freq_mode) {
+ /* Set periph_clk to be sourced from OSC_CLK */
+ clk_set_parent(periph_clk2_sel_clk, osc_clk);
+ clk_set_parent(periph_clk, periph_clk2_clk);
+ /* Ensure AHB/AXI clks are at 24MHz. */
+ clk_set_rate(ahb_clk, LPAPM_CLK);
+ clk_set_rate(ocram_clk, LPAPM_CLK);
+ }
+ if (audio_bus_count) {
+ /* Set AHB to 8MHz to lower pwer.*/
+ clk_set_rate(ahb_clk, LPAPM_CLK / 3);
+
+ /* Set up DDR to 100MHz. */
+ busfreq_func.update(HIGH_AUDIO_CLK);
+
+ /* Fix the clock tree in kernel */
+ clk_set_parent(periph2_pre_clk, pll2_200_clk);
+ clk_set_parent(periph2_clk, periph2_pre_clk);
+
+ if (low_bus_freq_mode || ultra_low_bus_freq_mode) {
+ /*
+ * Fix the clock tree in kernel, make sure
+ * pll2_bypass is updated as it is
+ * sourced from PLL2.
+ */
+ clk_set_parent(pll2_bypass_clk, pll2_clk);
+ /*
+ * Swtich ARM to run off PLL2_PFD2_400MHz
+ * since DDR is anyway at 100MHz.
+ */
+ clk_set_parent(step_clk, pll2_400_clk);
+ clk_set_parent(pll1_sw_clk, step_clk);
+
+ /*
+ * Need to ensure that PLL1 is bypassed and enabled
+ * before ARM-PODF is set.
+ */
+ clk_set_parent(pll1_bypass_clk, pll1_bypass_src_clk);
+
+ /*
+ * Ensure that the clock will be
+ * at original speed.
+ */
+ clk_set_rate(arm_clk, org_arm_rate);
+ }
+ low_bus_freq_mode = 0;
+ ultra_low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 1;
+ cur_bus_freq_mode = BUS_FREQ_AUDIO;
+ } else {
+ u32 arm_div, pll1_rate;
+ org_arm_rate = clk_get_rate(arm_clk);
+ if (org_arm_rate == 0) {
+ WARN_ON(1);
+ return;
+ }
+ if (low_bus_freq_mode && low_bus_count == 0) {
+ /*
+ * We are already in DDR @ 24MHz state, but
+ * no one but ARM needs the DDR. In this case,
+ * we can lower the DDR freq to 1MHz when ARM
+ * enters WFI in this state. Keep track of this state.
+ */
+ ultra_low_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_ULTRA_LOW;
+ } else {
+ if (!ultra_low_bus_freq_mode && !low_bus_freq_mode) {
+ /*
+ * Anyway, make sure the AHB is running at 24MHz
+ * in low_bus_freq_mode.
+ */
+ if (audio_bus_freq_mode)
+ clk_set_rate(ahb_clk, LPAPM_CLK);
+ /*
+ * Set DDR to 24MHz.
+ * Since we are going to bypass PLL2,
+ * we need to move ARM clk off PLL2_PFD2
+ * to PLL1. Make sure the PLL1 is running
+ * at the lowest possible freq.
+ * To work well with CPUFREQ we want to ensure that
+ * the CPU freq does not change, so attempt to
+ * get a freq as close to 396MHz as possible.
+ */
+ clk_set_rate(pll1_clk,
+ clk_round_rate(pll1_clk, (org_arm_rate * 2)));
+ pll1_rate = clk_get_rate(pll1_clk);
+ arm_div = pll1_rate / org_arm_rate;
+ if (pll1_rate / arm_div > org_arm_rate)
+ arm_div++;
+ /*
+ * Need to ensure that PLL1 is bypassed and enabled
+ * before ARM-PODF is set.
+ */
+ clk_set_parent(pll1_bypass_clk, pll1_clk);
+ /*
+ * Ensure ARM CLK is lower before
+ * changing the parent.
+ */
+ clk_set_rate(arm_clk, org_arm_rate / arm_div);
+ /* Now set the ARM clk parent to PLL1_SYS. */
+ clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+
+ /*
+ * Set STEP_CLK back to OSC to save power and
+ * also to maintain the parent.The WFI iram code
+ * will switch step_clk to osc, but the clock API
+ * is not aware of the change and when a new request
+ * to change the step_clk parent to pll2_pfd2_400M
+ * is requested sometime later, the change is ignored.
+ */
+ clk_set_parent(step_clk, osc_clk);
+
+ /* Now set DDR to 24MHz. */
+ busfreq_func.update(LPAPM_CLK);
+
+ /*
+ * Fix the clock tree in kernel.
+ * Make sure PLL2 rate is updated as it gets
+ * bypassed in the DDR freq change code.
+ */
+ clk_set_parent(pll2_bypass_clk, pll2_bypass_src_clk);
+ clk_set_parent(periph2_clk2_sel_clk, pll2_bus_clk);
+ clk_set_parent(periph2_clk, periph2_clk2_clk);
+ }
+ if (low_bus_count == 0) {
+ ultra_low_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_ULTRA_LOW;
+ } else {
+ ultra_low_bus_freq_mode = 0;
+ low_bus_freq_mode = 1;
+ cur_bus_freq_mode = BUS_FREQ_LOW;
+ }
+ audio_bus_freq_mode = 0;
+ }
+ }
+}
+
+static void exit_lpm_imx6sl(void)
+{
+ /* Change DDR freq in IRAM. */
+ busfreq_func.update(ddr_normal_rate);
+
+ /*
+ * Fix the clock tree in kernel.
+ * Make sure PLL2 rate is updated as it gets
+ * un-bypassed in the DDR freq change code.
+ */
+ clk_set_parent(pll2_bypass_clk, pll2_clk);
+ clk_set_parent(periph2_pre_clk, pll2_400_clk);
+ clk_set_parent(periph2_clk, periph2_pre_clk);
+
+ /* Ensure that periph_clk is sourced from PLL2_400. */
+ clk_set_parent(periph_pre_clk, pll2_400_clk);
+ /*
+ * Before switching the perhiph_clk, ensure that the
+ * AHB/AXI will not be too fast.
+ */
+ clk_set_rate(ahb_clk, LPAPM_CLK / 3);
+ clk_set_rate(ocram_clk, LPAPM_CLK / 2);
+ clk_set_parent(periph_clk, periph_pre_clk);
+
+ if (low_bus_freq_mode || ultra_low_bus_freq_mode) {
+ /* Move ARM from PLL1_SW_CLK to PLL2_400. */
+ clk_set_parent(step_clk, pll2_400_clk);
+ clk_set_parent(pll1_sw_clk, step_clk);
+ /*
+ * Need to ensure that PLL1 is bypassed and enabled
+ * before ARM-PODF is set.
+ */
+ clk_set_parent(pll1_bypass_clk, pll1_bypass_src_clk);
+ clk_set_rate(arm_clk, org_arm_rate);
+ ultra_low_bus_freq_mode = 0;
+ }
+}
+
+static void enter_lpm_imx7d(void)
+{
+ /*
+ * The AHB clock parent switch and divider change
+ * needs to keep previous/current parent enabled
+ * per design requirement, but when we switch the
+ * clock parent, previous AHB clock parent may be
+ * disabled by common clock framework, so here we
+ * have to make sure AHB's previous parent pfd2_270m
+ * is enabled during AHB set rate.
+ */
+ clk_prepare_enable(pfd2_270m);
+ if (audio_bus_count) {
+ clk_prepare_enable(pfd0_392m);
+ busfreq_func.update(HIGH_AUDIO_CLK);
+
+ clk_set_parent(dram_alt_sel, pfd0_392m);
+ clk_set_parent(dram_root, dram_alt_root);
+ if (high_bus_freq_mode) {
+ clk_set_parent(axi_sel_clk, osc_clk);
+ clk_set_parent(ahb_sel_clk, osc_clk);
+ clk_set_rate(ahb_clk, LPAPM_CLK);
+ }
+ clk_disable_unprepare(pfd0_392m);
+ audio_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_AUDIO;
+ } else {
+ busfreq_func.update(LPAPM_CLK);
+
+ clk_set_parent(dram_alt_sel, osc_clk);
+ clk_set_parent(dram_root, dram_alt_root);
+ if (high_bus_freq_mode) {
+ clk_set_parent(axi_sel_clk, osc_clk);
+ clk_set_parent(ahb_sel_clk, osc_clk);
+ clk_set_rate(ahb_clk, LPAPM_CLK);
+ }
+ low_bus_freq_mode = 1;
+ audio_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_LOW;
+ }
+ clk_disable_unprepare(pfd2_270m);
+}
+
+static void exit_lpm_imx7d(void)
+{
+ clk_set_parent(axi_sel_clk, pfd1_332m);
+ clk_set_rate(ahb_clk, LPAPM_CLK / 2);
+ clk_set_parent(ahb_sel_clk, pfd2_270m);
+
+ busfreq_func.update(ddr_normal_rate);
+
+ clk_set_parent(dram_root, pll_dram);
+}
+
+static void reduce_bus_freq(void)
+{
+ if (cpu_is_imx6())
+ clk_prepare_enable(pll3_clk);
+
+ if (audio_bus_count && (low_bus_freq_mode || ultra_low_bus_freq_mode))
+ busfreq_notify(LOW_BUSFREQ_EXIT);
+ else if (!audio_bus_count)
+ busfreq_notify(LOW_BUSFREQ_ENTER);
+
+ if (cpu_is_imx7d())
+ enter_lpm_imx7d();
+ else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ enter_lpm_imx6_up();
+ else if (cpu_is_imx6q() || cpu_is_imx6dl())
+ enter_lpm_imx6_smp();
+ else if (cpu_is_imx6sl())
+ enter_lpm_imx6sl();
+
+ med_bus_freq_mode = 0;
+ high_bus_freq_mode = 0;
+
+ if (cpu_is_imx6())
+ clk_disable_unprepare(pll3_clk);
+
+ if (audio_bus_freq_mode)
+ dev_dbg(busfreq_dev,
+ "Bus freq set to audio mode. Count: high %d, med %d, audio %d\n",
+ high_bus_count, med_bus_count, audio_bus_count);
+ if (low_bus_freq_mode)
+ dev_dbg(busfreq_dev,
+ "Bus freq set to low mode. Count: high %d, med %d, audio %d\n",
+ high_bus_count, med_bus_count, audio_bus_count);
+}
+
+static inline void cancel_low_bus_freq_handler(void)
+{
+ cancel_delayed_work(&low_bus_freq_handler);
+ cancel_reduce_bus_freq = true;
+}
+
+static void reduce_bus_freq_handler(struct work_struct *work)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (!cancel_reduce_bus_freq) {
+ reduce_bus_freq();
+ cancel_low_bus_freq_handler();
+ }
+
+ mutex_unlock(&bus_freq_mutex);
+}
+
+/*
+ * Set the DDR, AHB to 24MHz.
+ * This mode will be activated only when none of the modules that
+ * need a higher DDR or AHB frequency are active.
+ */
+static int set_low_bus_freq(void)
+{
+ if (busfreq_suspended)
+ return 0;
+
+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
+ return 0;
+
+ cancel_reduce_bus_freq = false;
+
+ /*
+ * Check to see if we need to got from
+ * low bus freq mode to audio bus freq mode.
+ * If so, the change needs to be done immediately.
+ */
+ if (audio_bus_count && (low_bus_freq_mode || ultra_low_bus_freq_mode))
+ reduce_bus_freq();
+ else
+ /*
+ * Don't lower the frequency immediately. Instead
+ * scheduled a delayed work and drop the freq if
+ * the conditions still remain the same.
+ */
+ schedule_delayed_work(&low_bus_freq_handler,
+ usecs_to_jiffies(3000000));
+ return 0;
+}
+
+/*
+ * Set the DDR to either 528MHz or 400MHz for iMX6qd
+ * or 400MHz for iMX6dl.
+ */
+static int set_high_bus_freq(int high_bus_freq)
+{
+ if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
+ cancel_low_bus_freq_handler();
+
+ if (busfreq_suspended)
+ return 0;
+
+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
+ return 0;
+
+ if (high_bus_freq_mode)
+ return 0;
+
+ /* medium bus freq is only supported for MX6DQ */
+ if (med_bus_freq_mode && !high_bus_freq)
+ return 0;
+
+ if (low_bus_freq_mode || ultra_low_bus_freq_mode)
+ busfreq_notify(LOW_BUSFREQ_EXIT);
+
+ if (cpu_is_imx6())
+ clk_prepare_enable(pll3_clk);
+
+ if (cpu_is_imx7d())
+ exit_lpm_imx7d();
+ else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ exit_lpm_imx6_up();
+ else if (cpu_is_imx6q() || cpu_is_imx6dl())
+ exit_lpm_imx6_smp();
+ else if (cpu_is_imx6sl())
+ exit_lpm_imx6sl();
+
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_HIGH;
+
+ if (cpu_is_imx6())
+ clk_disable_unprepare(pll3_clk);
+
+ if (high_bus_freq_mode)
+ dev_dbg(busfreq_dev,
+ "Bus freq set to high mode. Count: high %d, med %d, audio %d\n",
+ high_bus_count, med_bus_count, audio_bus_count);
+ if (med_bus_freq_mode)
+ dev_dbg(busfreq_dev,
+ "Bus freq set to med mode. Count: high %d, med %d, audio %d\n",
+ high_bus_count, med_bus_count, audio_bus_count);
+
+ return 0;
+}
+
+void request_bus_freq(enum bus_freq_mode mode)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (mode == BUS_FREQ_ULTRA_LOW) {
+ dev_dbg(busfreq_dev, "This mode cannot be requested!\n");
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ if (mode == BUS_FREQ_HIGH)
+ high_bus_count++;
+ else if (mode == BUS_FREQ_MED)
+ med_bus_count++;
+ else if (mode == BUS_FREQ_AUDIO)
+ audio_bus_count++;
+ else if (mode == BUS_FREQ_LOW)
+ low_bus_count++;
+
+ if (busfreq_suspended || !bus_freq_scaling_initialized ||
+ !bus_freq_scaling_is_active) {
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ cancel_low_bus_freq_handler();
+
+ if ((mode == BUS_FREQ_HIGH) && (!high_bus_freq_mode)) {
+ set_high_bus_freq(1);
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ if ((mode == BUS_FREQ_MED) && (!high_bus_freq_mode) &&
+ (!med_bus_freq_mode)) {
+ set_high_bus_freq(0);
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ if ((mode == BUS_FREQ_AUDIO) && (!high_bus_freq_mode) &&
+ (!med_bus_freq_mode) && (!audio_bus_freq_mode)) {
+ set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ mutex_unlock(&bus_freq_mutex);
+}
+EXPORT_SYMBOL(request_bus_freq);
+
+void release_bus_freq(enum bus_freq_mode mode)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (mode == BUS_FREQ_ULTRA_LOW) {
+ dev_dbg(busfreq_dev,
+ "This mode cannot be released!\n");
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ if (mode == BUS_FREQ_HIGH) {
+ if (high_bus_count == 0) {
+ dev_err(busfreq_dev, "high bus count mismatch!\n");
+ dump_stack();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ high_bus_count--;
+ } else if (mode == BUS_FREQ_MED) {
+ if (med_bus_count == 0) {
+ dev_err(busfreq_dev, "med bus count mismatch!\n");
+ dump_stack();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ med_bus_count--;
+ } else if (mode == BUS_FREQ_AUDIO) {
+ if (audio_bus_count == 0) {
+ dev_err(busfreq_dev, "audio bus count mismatch!\n");
+ dump_stack();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ audio_bus_count--;
+ } else if (mode == BUS_FREQ_LOW) {
+ if (low_bus_count == 0) {
+ dev_err(busfreq_dev, "low bus count mismatch!\n");
+ dump_stack();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ low_bus_count--;
+ }
+
+ if (busfreq_suspended || !bus_freq_scaling_initialized ||
+ !bus_freq_scaling_is_active) {
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ if ((!audio_bus_freq_mode) && (high_bus_count == 0) &&
+ (med_bus_count == 0) && (audio_bus_count != 0)) {
+ set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ if ((!low_bus_freq_mode) && (high_bus_count == 0) &&
+ (med_bus_count == 0) && (audio_bus_count == 0) &&
+ (low_bus_count != 0)) {
+ set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+ if ((!ultra_low_bus_freq_mode) && (high_bus_count == 0) &&
+ (med_bus_count == 0) && (audio_bus_count == 0) &&
+ (low_bus_count == 0)) {
+ set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
+ return;
+ }
+
+ mutex_unlock(&bus_freq_mutex);
+}
+EXPORT_SYMBOL(release_bus_freq);
+
+int get_bus_freq_mode(void)
+{
+ return cur_bus_freq_mode;
+}
+EXPORT_SYMBOL(get_bus_freq_mode);
+
+static struct map_desc ddr_iram_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_1M,
+ .type = MT_MEMORY_RWX_NONCACHED,
+};
+
+const static char *ddr_freq_iram_match[] __initconst = {
+ "fsl,ddr-lpm-sram",
+ NULL
+};
+
+static int __init imx_dt_find_ddr_sram(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ unsigned long ddr_iram_addr;
+ const __be32 *prop;
+
+ if (of_flat_dt_match(node, ddr_freq_iram_match)) {
+ unsigned int len;
+
+ prop = of_get_flat_dt_prop(node, "reg", &len);
+ if (prop == NULL || len != (sizeof(unsigned long) * 2))
+ return -EINVAL;
+ ddr_iram_addr = be32_to_cpu(prop[0]);
+ ddr_freq_change_total_size = be32_to_cpu(prop[1]);
+ ddr_freq_change_iram_phys = ddr_iram_addr;
+
+ /* Make sure ddr_freq_change_iram_phys is 8 byte aligned. */
+ if ((uintptr_t)(ddr_freq_change_iram_phys) & (FNCPY_ALIGN - 1))
+ ddr_freq_change_iram_phys += FNCPY_ALIGN -
+ ((uintptr_t)ddr_freq_change_iram_phys %
+ (FNCPY_ALIGN));
+ }
+ return 0;
+}
+
+void __init imx_busfreq_map_io(void)
+{
+ /*
+ * Get the address of IRAM to be used by the ddr frequency
+ * change code from the device tree.
+ */
+ WARN_ON(of_scan_flat_dt(imx_dt_find_ddr_sram, NULL));
+ if (ddr_freq_change_iram_phys) {
+ ddr_freq_change_iram_base = IMX_IO_P2V(
+ ddr_freq_change_iram_phys);
+ if ((iram_tlb_phys_addr & 0xFFF00000) !=
+ (ddr_freq_change_iram_phys & 0xFFF00000)) {
+ /* We need to create a 1M page table entry. */
+ ddr_iram_io_desc.virtual = IMX_IO_P2V(
+ ddr_freq_change_iram_phys & 0xFFF00000);
+ ddr_iram_io_desc.pfn = __phys_to_pfn(
+ ddr_freq_change_iram_phys & 0xFFF00000);
+ iotable_init(&ddr_iram_io_desc, 1);
+ }
+ memset((void *)ddr_freq_change_iram_base, 0,
+ ddr_freq_change_total_size);
+ }
+}
+
+static void bus_freq_daemon_handler(struct work_struct *work)
+{
+ mutex_lock(&bus_freq_mutex);
+ if ((!low_bus_freq_mode) && (!ultra_low_bus_freq_mode)
+ && (high_bus_count == 0) &&
+ (med_bus_count == 0) && (audio_bus_count == 0))
+ set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
+}
+
+static ssize_t bus_freq_scaling_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (bus_freq_scaling_is_active)
+ return sprintf(buf, "Bus frequency scaling is enabled\n");
+ else
+ return sprintf(buf, "Bus frequency scaling is disabled\n");
+}
+
+static ssize_t bus_freq_scaling_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (strncmp(buf, "1", 1) == 0) {
+ bus_freq_scaling_is_active = 1;
+ set_high_bus_freq(1);
+ /*
+ * We set bus freq to highest at the beginning,
+ * so we use this daemon thread to make sure system
+ * can enter low bus mode if
+ * there is no high bus request pending
+ */
+ schedule_delayed_work(&bus_freq_daemon,
+ usecs_to_jiffies(5000000));
+ } else if (strncmp(buf, "0", 1) == 0) {
+ if (bus_freq_scaling_is_active)
+ set_high_bus_freq(1);
+ bus_freq_scaling_is_active = 0;
+ }
+ return size;
+}
+
+static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (event == PM_SUSPEND_PREPARE) {
+ if (cpu_is_imx7d() && imx_src_is_m4_enabled())
+ imx_mu_lpm_ready(false);
+ high_bus_count++;
+ set_high_bus_freq(1);
+ busfreq_suspended = 1;
+ } else if (event == PM_POST_SUSPEND) {
+ busfreq_suspended = 0;
+ high_bus_count--;
+ if (cpu_is_imx7d() && imx_src_is_m4_enabled())
+ imx_mu_lpm_ready(true);
+ schedule_delayed_work(&bus_freq_daemon,
+ usecs_to_jiffies(5000000));
+ }
+
+ mutex_unlock(&bus_freq_mutex);
+
+ return NOTIFY_OK;
+}
+
+static int busfreq_reboot_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ /* System is rebooting. Set the system into high_bus_freq_mode. */
+ request_bus_freq(BUS_FREQ_HIGH);
+
+ return 0;
+}
+
+static struct notifier_block imx_bus_freq_pm_notifier = {
+ .notifier_call = bus_freq_pm_notify,
+};
+
+static struct notifier_block imx_busfreq_reboot_notifier = {
+ .notifier_call = busfreq_reboot_notifier_event,
+};
+
+
+static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
+ bus_freq_scaling_enable_store);
+
+/*!
+ * This is the probe routine for the bus frequency driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+
+static int busfreq_probe(struct platform_device *pdev)
+{
+ u32 err;
+
+ busfreq_dev = &pdev->dev;
+
+ /* Return if no IRAM space is allocated for ddr freq change code. */
+ if (!ddr_freq_change_iram_base)
+ return -ENOMEM;
+
+ if (cpu_is_imx6()) {
+ osc_clk = devm_clk_get(&pdev->dev, "osc");
+ pll2_400_clk = devm_clk_get(&pdev->dev, "pll2_pfd2_396m");
+ pll2_200_clk = devm_clk_get(&pdev->dev, "pll2_198m");
+ pll2_bus_clk = devm_clk_get(&pdev->dev, "pll2_bus");
+ pll3_clk = devm_clk_get(&pdev->dev, "pll3_usb_otg");
+ periph_clk = devm_clk_get(&pdev->dev, "periph");
+ periph_pre_clk = devm_clk_get(&pdev->dev, "periph_pre");
+ periph_clk2_clk = devm_clk_get(&pdev->dev, "periph_clk2");
+ periph_clk2_sel_clk = devm_clk_get(&pdev->dev,
+ "periph_clk2_sel");
+ if (IS_ERR(osc_clk) || IS_ERR(pll2_400_clk)
+ || IS_ERR(pll2_200_clk) || IS_ERR(pll2_bus_clk)
+ || IS_ERR(pll3_clk) || IS_ERR(periph_clk)
+ || IS_ERR(periph_pre_clk) || IS_ERR(periph_clk2_clk)
+ || IS_ERR(periph_clk2_sel_clk)) {
+ dev_err(busfreq_dev,
+ "%s: failed to get busfreq clk\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6dl()) {
+ axi_alt_sel_clk = devm_clk_get(&pdev->dev, "axi_alt_sel");
+ axi_sel_clk = devm_clk_get(&pdev->dev, "axi_sel");
+ pll3_pfd1_540m_clk = devm_clk_get(&pdev->dev, "pll3_pfd1_540m");
+ if (IS_ERR(axi_alt_sel_clk) || IS_ERR(axi_sel_clk)
+ || IS_ERR(pll3_pfd1_540m_clk)) {
+ dev_err(busfreq_dev,
+ "%s: failed to get busfreq clk\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6sx() || cpu_is_imx6sl() || cpu_is_imx6ul() ||
+ cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) {
+ ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+ ocram_clk = devm_clk_get(&pdev->dev, "ocram");
+ periph2_clk = devm_clk_get(&pdev->dev, "periph2");
+ periph2_pre_clk = devm_clk_get(&pdev->dev, "periph2_pre");
+ periph2_clk2_clk = devm_clk_get(&pdev->dev, "periph2_clk2");
+ periph2_clk2_sel_clk =
+ devm_clk_get(&pdev->dev, "periph2_clk2_sel");
+ if (IS_ERR(ahb_clk) || IS_ERR(ocram_clk)
+ || IS_ERR(periph2_clk) || IS_ERR(periph2_pre_clk)
+ || IS_ERR(periph2_clk2_clk)
+ || IS_ERR(periph2_clk2_sel_clk)) {
+ dev_err(busfreq_dev,
+ "%s: failed to get busfreq clk for imx6ul/sx/sl.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll()) {
+ mmdc_clk = devm_clk_get(&pdev->dev, "mmdc");
+ if (IS_ERR(mmdc_clk)) {
+ dev_err(busfreq_dev,
+ "%s: failed to get mmdc clk for imx6sx/ul.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6q()) {
+ mmdc_clk = devm_clk_get(&pdev->dev, "mmdc");
+ if (IS_ERR(mmdc_clk)) {
+ mmdc_clk = NULL;
+ }
+ }
+
+ if (cpu_is_imx6sx()) {
+ m4_clk = devm_clk_get(&pdev->dev, "m4");
+ if (IS_ERR(m4_clk)) {
+ dev_err(busfreq_dev, "%s: failed to get m4 clk.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6sl()) {
+ pll2_bypass_src_clk = devm_clk_get(&pdev->dev, "pll2_bypass_src");
+ pll2_bypass_clk = devm_clk_get(&pdev->dev, "pll2_bypass");
+ pll2_clk = devm_clk_get(&pdev->dev, "pll2");
+ if (IS_ERR(pll2_bypass_src_clk) || IS_ERR(pll2_bypass_clk)
+ || IS_ERR(pll2_clk)) {
+ dev_err(busfreq_dev,
+ "%s failed to get busfreq clk for imx6sl.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx6sl() || cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) {
+ arm_clk = devm_clk_get(&pdev->dev, "arm");
+ step_clk = devm_clk_get(&pdev->dev, "step");
+ pll1_clk = devm_clk_get(&pdev->dev, "pll1");
+ pll1_bypass_src_clk = devm_clk_get(&pdev->dev, "pll1_bypass_src");
+ pll1_bypass_clk = devm_clk_get(&pdev->dev, "pll1_bypass");
+ pll1_sys_clk = devm_clk_get(&pdev->dev, "pll1_sys");
+ pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw");
+ if (IS_ERR(arm_clk) || IS_ERR(step_clk) || IS_ERR(pll1_clk)
+ || IS_ERR(pll1_bypass_src_clk) || IS_ERR(pll1_bypass_clk)
+ || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk)) {
+ dev_err(busfreq_dev, "%s failed to get busfreq clk for imx6ull/sl.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (cpu_is_imx7d()) {
+ osc_clk = devm_clk_get(&pdev->dev, "osc");
+ axi_sel_clk = devm_clk_get(&pdev->dev, "axi_sel");
+ ahb_sel_clk = devm_clk_get(&pdev->dev, "ahb_sel");
+ pfd0_392m = devm_clk_get(&pdev->dev, "pfd0_392m");
+ dram_root = devm_clk_get(&pdev->dev, "dram_root");
+ dram_alt_sel = devm_clk_get(&pdev->dev, "dram_alt_sel");
+ pll_dram = devm_clk_get(&pdev->dev, "pll_dram");
+ dram_alt_root = devm_clk_get(&pdev->dev, "dram_alt_root");
+ pfd1_332m = devm_clk_get(&pdev->dev, "pfd1_332m");
+ pfd2_270m = devm_clk_get(&pdev->dev, "pfd2_270m");
+ ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+ axi_clk = devm_clk_get(&pdev->dev, "axi");
+ if (IS_ERR(osc_clk) || IS_ERR(axi_sel_clk) || IS_ERR(ahb_clk)
+ || IS_ERR(pfd0_392m) || IS_ERR(dram_root)
+ || IS_ERR(dram_alt_sel) || IS_ERR(pll_dram)
+ || IS_ERR(dram_alt_root) || IS_ERR(pfd1_332m)
+ || IS_ERR(ahb_clk) || IS_ERR(axi_clk)
+ || IS_ERR(pfd2_270m)) {
+ dev_err(busfreq_dev,
+ "%s: failed to get busfreq clk\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+ if (err) {
+ dev_err(busfreq_dev,
+ "Unable to register sysdev entry for BUSFREQ");
+ return err;
+ }
+
+ if (of_property_read_u32(pdev->dev.of_node, "fsl,max_ddr_freq",
+ &ddr_normal_rate)) {
+ dev_err(busfreq_dev, "max_ddr_freq entry missing\n");
+ return -EINVAL;
+ }
+
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ low_bus_freq_mode = 0;
+ audio_bus_freq_mode = 0;
+ ultra_low_bus_freq_mode = 0;
+ cur_bus_freq_mode = BUS_FREQ_HIGH;
+
+ bus_freq_scaling_is_active = 1;
+ bus_freq_scaling_initialized = 1;
+
+ ddr_low_rate = LPAPM_CLK;
+
+ INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
+ INIT_DELAYED_WORK(&bus_freq_daemon, bus_freq_daemon_handler);
+ register_pm_notifier(&imx_bus_freq_pm_notifier);
+ register_reboot_notifier(&imx_busfreq_reboot_notifier);
+
+ /* enter low bus mode if no high speed device enabled */
+ schedule_delayed_work(&bus_freq_daemon,
+ msecs_to_jiffies(20000));
+
+ /*
+ * Need to make sure to an entry for the ddr freq change code
+ * address in the IRAM page table.
+ * This is only required if the DDR freq code and suspend/idle
+ * code are in different OCRAM spaces.
+ */
+ if ((iram_tlb_phys_addr & 0xFFF00000) !=
+ (ddr_freq_change_iram_phys & 0xFFF00000)) {
+ unsigned long i;
+
+ /*
+ * Make sure the ddr_iram virtual address has a mapping
+ * in the IRAM page table.
+ */
+ i = ((IMX_IO_P2V(ddr_freq_change_iram_phys) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (ddr_freq_change_iram_phys & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ }
+
+ if (cpu_is_imx7d()) {
+ ddr_type = imx_ddrc_get_ddr_type();
+ /* reduce ddr3 normal rate to 400M due to CKE issue on TO1.1 */
+ if (imx_get_soc_revision() == IMX_CHIP_REVISION_1_1 &&
+ ddr_type == IMX_DDR_TYPE_DDR3) {
+ ddr_normal_rate = 400000000;
+ pr_info("ddr3 normal rate changed to 400MHz for TO1.1.\n");
+ }
+ busfreq_func.init = &init_ddrc_ddr_settings;
+ busfreq_func.update = &update_ddr_freq_imx_smp;
+ } else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz() ||
+ cpu_is_imx6sll()) {
+ ddr_type = imx_mmdc_get_ddr_type();
+ if (ddr_type == IMX_DDR_TYPE_DDR3) {
+ busfreq_func.init = &init_mmdc_ddr3_settings_imx6_up;
+ busfreq_func.update = &update_ddr_freq_imx6_up;
+ } else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3) {
+ busfreq_func.init = &init_mmdc_lpddr2_settings;
+ busfreq_func.update = &update_lpddr2_freq;
+ }
+ } else if (cpu_is_imx6q() || cpu_is_imx6dl()) {
+ ddr_type = imx_mmdc_get_ddr_type();
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3) {
+ busfreq_func.init = &init_mmdc_ddr3_settings_imx6_smp;
+ busfreq_func.update = &update_ddr_freq_imx_smp;
+ } else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2) {
+ busfreq_func.init = &init_mmdc_lpddr2_settings_mx6q;
+ busfreq_func.update = &update_lpddr2_freq_smp;
+ }
+ } else if (cpu_is_imx6sl()) {
+ busfreq_func.init = &init_mmdc_lpddr2_settings;
+ busfreq_func.update = &update_lpddr2_freq;
+ }
+
+ if (busfreq_func.init)
+ err = busfreq_func.init(pdev);
+ else
+ err = -EINVAL;
+
+ if (!err) {
+ if (cpu_is_imx6sx()) {
+ /*
+ * If M4 is enabled and rate > 24MHz,
+ * add high bus count
+ */
+ if (imx_src_is_m4_enabled() &&
+ (clk_get_rate(m4_clk) > LPAPM_CLK))
+ high_bus_count++;
+ }
+
+ if (cpu_is_imx7d() && imx_src_is_m4_enabled()) {
+ high_bus_count++;
+ imx_mu_lpm_ready(true);
+ }
+ }
+
+ if (err) {
+ dev_err(busfreq_dev, "Busfreq init of ddr controller failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id imx_busfreq_ids[] = {
+ { .compatible = "fsl,imx_busfreq", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver busfreq_driver = {
+ .driver = {
+ .name = "imx_busfreq",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_busfreq_ids,
+ },
+ .probe = busfreq_probe,
+};
+
+/*!
+ * Initialise the busfreq_driver.
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init busfreq_init(void)
+{
+#ifndef CONFIG_MX6_VPU_352M
+ if (platform_driver_register(&busfreq_driver) != 0)
+ return -ENODEV;
+
+ pr_info("Bus freq driver module loaded\n");
+#endif
+ return 0;
+}
+
+static void __exit busfreq_cleanup(void)
+{
+ sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&busfreq_driver);
+ bus_freq_scaling_initialized = 0;
+}
+
+module_init(busfreq_init);
+module_exit(busfreq_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("BusFreq driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-imx/busfreq_ddr3.c b/arch/arm/mach-imx/busfreq_ddr3.c
new file mode 100644
index 000000000000..0088a5d80736
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -0,0 +1,772 @@
+/*
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. 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
+ */
+
+/*!
+ * @file busfreq_ddr3.c
+ *
+ * @brief iMX6 DDR3 frequency change specific file.
+ *
+ * @ingroup PM
+ */
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/tlb.h>
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+
+#include "hardware.h"
+#include "common.h"
+
+#define SMP_WFE_CODE_SIZE 0x400
+
+#define MIN_DLL_ON_FREQ 333000000
+#define MAX_DLL_OFF_FREQ 125000000
+#define MMDC0_MPMUR0 0x8b8
+#define MMDC0_MPMUR0_OFFSET 16
+#define MMDC0_MPMUR0_MASK 0x3ff
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * busfreq code(arch/arm/mach-imx/ddr3_freq_imx6.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/ddr3_freq_imx6.S must be also changed accordingly,
+ * otherwise, the busfreq change function will be broken!
+ *
+ * This structure will be placed in front of the asm code on ocram.
+ */
+struct imx6_busfreq_info {
+ u32 freq;
+ void *ddr_settings;
+ u32 dll_off;
+ void *iomux_offsets;
+ u32 mu_delay_val;
+} __aligned(8);
+
+static struct imx6_busfreq_info *imx6_busfreq_info;
+
+/* DDR settings */
+static unsigned long (*iram_ddr_settings)[2];
+static unsigned long (*normal_mmdc_settings)[2];
+static unsigned long (*iram_iomux_settings)[2];
+
+static void __iomem *mmdc_base;
+static void __iomem *iomux_base;
+static void __iomem *gic_dist_base;
+
+static int ddr_settings_size;
+static int iomux_settings_size;
+static int curr_ddr_rate;
+
+void (*imx6_up_change_ddr_freq)(struct imx6_busfreq_info *busfreq_info);
+extern void imx6_up_ddr3_freq_change(struct imx6_busfreq_info *busfreq_info);
+void (*imx7d_change_ddr_freq)(u32 freq) = NULL;
+extern void imx7d_ddr3_freq_change(u32 freq);
+extern void imx_lpddr3_freq_change(u32 freq);
+
+void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings,
+ bool dll_mode, void *iomux_offsets) = NULL;
+
+extern unsigned int ddr_normal_rate;
+extern int low_bus_freq_mode;
+extern int audio_bus_freq_mode;
+extern void mx6_ddr3_freq_change(u32 freq, void *ddr_settings,
+ bool dll_mode, void *iomux_offsets);
+
+extern unsigned long save_ttbr1(void);
+extern void restore_ttbr1(unsigned long ttbr1);
+extern unsigned long ddr_freq_change_iram_base;
+
+extern unsigned long ddr_freq_change_total_size;
+extern unsigned long iram_tlb_phys_addr;
+
+extern unsigned long mx6_ddr3_freq_change_start asm("mx6_ddr3_freq_change_start");
+extern unsigned long mx6_ddr3_freq_change_end asm("mx6_ddr3_freq_change_end");
+extern unsigned long imx6_up_ddr3_freq_change_start asm("imx6_up_ddr3_freq_change_start");
+extern unsigned long imx6_up_ddr3_freq_change_end asm("imx6_up_ddr3_freq_change_end");
+
+#ifdef CONFIG_SMP
+static unsigned long wfe_freq_change_iram_base;
+volatile u32 *wait_for_ddr_freq_update;
+static unsigned int online_cpus;
+static u32 *irqs_used;
+
+void (*wfe_change_ddr_freq)(u32 cpuid, u32 *ddr_freq_change_done);
+void (*imx7_wfe_change_ddr_freq)(u32 cpuid, u32 ocram_base);
+extern void wfe_smp_freq_change(u32 cpuid, u32 *ddr_freq_change_done);
+extern void imx7_smp_wfe(u32 cpuid, u32 ocram_base);
+extern unsigned long wfe_smp_freq_change_start asm("wfe_smp_freq_change_start");
+extern unsigned long wfe_smp_freq_change_end asm("wfe_smp_freq_change_end");
+extern void __iomem *scu_base;
+#endif
+
+unsigned long ddr3_dll_mx6sx[][2] = {
+ {0x0c, 0x0},
+ {0x10, 0x0},
+ {0x1C, 0x04008032},
+ {0x1C, 0x00048031},
+ {0x1C, 0x05208030},
+ {0x1C, 0x04008040},
+ {0x818, 0x0},
+ {0x18, 0x0},
+};
+
+unsigned long ddr3_calibration_mx6sx[][2] = {
+ {0x83c, 0x0},
+ {0x840, 0x0},
+ {0x848, 0x0},
+ {0x850, 0x0},
+};
+
+unsigned long iomux_offsets_mx6sx[][2] = {
+ {0x330, 0x0},
+ {0x334, 0x0},
+ {0x338, 0x0},
+ {0x33c, 0x0},
+};
+
+unsigned long iomux_offsets_mx6ul[][2] = {
+ {0x280, 0x0},
+ {0x284, 0x0},
+};
+
+unsigned long ddr3_dll_mx6q[][2] = {
+ {0x0c, 0x0},
+ {0x10, 0x0},
+ {0x1C, 0x04088032},
+ {0x1C, 0x0408803a},
+ {0x1C, 0x08408030},
+ {0x1C, 0x08408038},
+ {0x818, 0x0},
+ {0x18, 0x0},
+};
+
+unsigned long ddr3_calibration[][2] = {
+ {0x83c, 0x0},
+ {0x840, 0x0},
+ {0x483c, 0x0},
+ {0x4840, 0x0},
+ {0x848, 0x0},
+ {0x4848, 0x0},
+ {0x850, 0x0},
+ {0x4850, 0x0},
+};
+
+unsigned long iomux_offsets_mx6q[][2] = {
+ {0x5A8, 0x0},
+ {0x5B0, 0x0},
+ {0x524, 0x0},
+ {0x51C, 0x0},
+ {0x518, 0x0},
+ {0x50C, 0x0},
+ {0x5B8, 0x0},
+ {0x5C0, 0x0},
+};
+
+unsigned long ddr3_dll_mx6dl[][2] = {
+ {0x0c, 0x0},
+ {0x10, 0x0},
+ {0x1C, 0x04008032},
+ {0x1C, 0x0400803a},
+ {0x1C, 0x07208030},
+ {0x1C, 0x07208038},
+ {0x818, 0x0},
+ {0x18, 0x0},
+};
+
+unsigned long iomux_offsets_mx6dl[][2] = {
+ {0x4BC, 0x0},
+ {0x4C0, 0x0},
+ {0x4C4, 0x0},
+ {0x4C8, 0x0},
+ {0x4CC, 0x0},
+ {0x4D0, 0x0},
+ {0x4D4, 0x0},
+ {0x4D8, 0x0},
+};
+
+int can_change_ddr_freq(void)
+{
+ return 1;
+}
+
+#ifdef CONFIG_SMP
+/*
+ * each active core apart from the one changing
+ * the DDR frequency will execute this function.
+ * the rest of the cores have to remain in WFE
+ * state until the frequency is changed.
+ */
+static irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
+{
+ u32 me;
+
+ me = smp_processor_id();
+#ifdef CONFIG_LOCAL_TIMERS
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+ &me);
+#endif
+ if (cpu_is_imx7d())
+ imx7_wfe_change_ddr_freq(0x8 * me,
+ (u32)ddr_freq_change_iram_base);
+ else
+ wfe_change_ddr_freq(0xff << (me * 8),
+ (u32 *)&iram_iomux_settings[0][1]);
+#ifdef CONFIG_LOCAL_TIMERS
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+ &me);
+#endif
+
+ return IRQ_HANDLED;
+}
+#endif
+
+/* change the DDR frequency. */
+int update_ddr_freq_imx_smp(int ddr_rate)
+{
+ int me = 0;
+ unsigned long ttbr1;
+ bool dll_off = false;
+ int i;
+#ifdef CONFIG_SMP
+ unsigned int reg = 0;
+ int cpu = 0;
+#endif
+ int mode = get_bus_freq_mode();
+
+ if (!can_change_ddr_freq())
+ return -1;
+
+ if (ddr_rate == curr_ddr_rate)
+ return 0;
+
+ printk(KERN_DEBUG "\nBus freq set to %d start...\n", ddr_rate);
+
+ if (cpu_is_imx6()) {
+ if ((mode == BUS_FREQ_LOW) || (mode == BUS_FREQ_AUDIO))
+ dll_off = true;
+
+ iram_ddr_settings[0][0] = ddr_settings_size;
+ iram_iomux_settings[0][0] = iomux_settings_size;
+ if (ddr_rate == ddr_normal_rate) {
+ for (i = 0; i < iram_ddr_settings[0][0]; i++) {
+ iram_ddr_settings[i + 1][0] =
+ normal_mmdc_settings[i][0];
+ iram_ddr_settings[i + 1][1] =
+ normal_mmdc_settings[i][1];
+ }
+ }
+ }
+
+ /* ensure that all Cores are in WFE. */
+ local_irq_disable();
+
+#ifdef CONFIG_SMP
+ me = smp_processor_id();
+
+ /* Make sure all the online cores are active */
+ while (1) {
+ bool not_exited_busfreq = false;
+ u32 reg = 0;
+
+ for_each_online_cpu(cpu) {
+ if (cpu_is_imx7d())
+ reg = *(wait_for_ddr_freq_update + 1);
+ else if (cpu_is_imx6())
+ reg = __raw_readl(scu_base + 0x08);
+
+ if (reg & (0x02 << (cpu * 8)))
+ not_exited_busfreq = true;
+ }
+ if (!not_exited_busfreq)
+ break;
+ }
+
+ wmb();
+ *wait_for_ddr_freq_update = 1;
+ dsb();
+ if (cpu_is_imx7d())
+ online_cpus = *(wait_for_ddr_freq_update + 1);
+ else if (cpu_is_imx6())
+ online_cpus = readl_relaxed(scu_base + 0x08);
+ for_each_online_cpu(cpu) {
+ *((char *)(&online_cpus) + (u8)cpu) = 0x02;
+ if (cpu != me) {
+ /* set the interrupt to be pending in the GIC. */
+ reg = 1 << (irqs_used[cpu] % 32);
+ writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET
+ + (irqs_used[cpu] / 32) * 4);
+ }
+ }
+ /* Wait for the other active CPUs to idle */
+ while (1) {
+ u32 reg = 0;
+
+ if (cpu_is_imx7d())
+ reg = *(wait_for_ddr_freq_update + 1);
+ else if (cpu_is_imx6())
+ reg = readl_relaxed(scu_base + 0x08);
+ reg |= (0x02 << (me * 8));
+ if (reg == online_cpus)
+ break;
+ }
+#endif
+
+ /* Ensure iram_tlb_phys_addr is flushed to DDR. */
+ __cpuc_flush_dcache_area(&iram_tlb_phys_addr,
+ sizeof(iram_tlb_phys_addr));
+ if (cpu_is_imx6())
+ outer_clean_range(__pa(&iram_tlb_phys_addr),
+ __pa(&iram_tlb_phys_addr + 1));
+
+ ttbr1 = save_ttbr1();
+ /* Now we can change the DDR frequency. */
+ if (cpu_is_imx7d())
+ imx7d_change_ddr_freq(ddr_rate);
+ else if (cpu_is_imx6())
+ mx6_change_ddr_freq(ddr_rate, iram_ddr_settings,
+ dll_off, iram_iomux_settings);
+ restore_ttbr1(ttbr1);
+ curr_ddr_rate = ddr_rate;
+
+#ifdef CONFIG_SMP
+ wmb();
+ /* DDR frequency change is done . */
+ *wait_for_ddr_freq_update = 0;
+ dsb();
+
+ /* wake up all the cores. */
+ sev();
+#endif
+
+ local_irq_enable();
+
+ printk(KERN_DEBUG "Bus freq set to %d done! cpu=%d\n", ddr_rate, me);
+
+ return 0;
+}
+
+/* Used by i.MX6SX/i.MX6UL for updating the ddr frequency */
+int update_ddr_freq_imx6_up(int ddr_rate)
+{
+ int i;
+ bool dll_off = false;
+ unsigned long ttbr1;
+ int mode = get_bus_freq_mode();
+
+ if (ddr_rate == curr_ddr_rate)
+ return 0;
+
+ printk(KERN_DEBUG "\nBus freq set to %d start...\n", ddr_rate);
+
+ if ((mode == BUS_FREQ_LOW) || (mode == BUS_FREQ_AUDIO))
+ dll_off = true;
+
+ imx6_busfreq_info->dll_off = dll_off;
+ iram_ddr_settings[0][0] = ddr_settings_size;
+ iram_iomux_settings[0][0] = iomux_settings_size;
+ for (i = 0; i < iram_ddr_settings[0][0]; i++) {
+ iram_ddr_settings[i + 1][0] =
+ normal_mmdc_settings[i][0];
+ iram_ddr_settings[i + 1][1] =
+ normal_mmdc_settings[i][1];
+ }
+
+ local_irq_disable();
+
+ ttbr1 = save_ttbr1();
+ imx6_busfreq_info->freq = ddr_rate;
+ imx6_busfreq_info->ddr_settings = iram_ddr_settings;
+ imx6_busfreq_info->iomux_offsets = iram_iomux_settings;
+ imx6_busfreq_info->mu_delay_val = ((readl_relaxed(mmdc_base + MMDC0_MPMUR0)
+ >> MMDC0_MPMUR0_OFFSET) & MMDC0_MPMUR0_MASK);
+
+ imx6_up_change_ddr_freq(imx6_busfreq_info);
+ restore_ttbr1(ttbr1);
+ curr_ddr_rate = ddr_rate;
+
+ local_irq_enable();
+
+ printk(KERN_DEBUG "Bus freq set to %d done!\n", ddr_rate);
+
+ return 0;
+}
+
+int init_ddrc_ddr_settings(struct platform_device *busfreq_pdev)
+{
+ int ddr_type = imx_ddrc_get_ddr_type();
+#ifdef CONFIG_SMP
+ struct device_node *node;
+ u32 cpu;
+ struct device *dev = &busfreq_pdev->dev;
+ int err;
+ struct irq_data *d;
+
+ node = of_find_compatible_node(NULL, NULL, "arm,cortex-a7-gic");
+ if (!node) {
+ printk(KERN_ERR "failed to find imx7d-a7-gic device tree data!\n");
+ return -EINVAL;
+ }
+ gic_dist_base = of_iomap(node, 0);
+ WARN(!gic_dist_base, "unable to map gic dist registers\n");
+
+ irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
+ GFP_KERNEL);
+ for_each_online_cpu(cpu) {
+ int irq;
+ /*
+ * set up a reserved interrupt to get all
+ * the active cores into a WFE state
+ * before changing the DDR frequency.
+ */
+ irq = platform_get_irq(busfreq_pdev, cpu);
+ err = request_irq(irq, wait_in_wfe_irq,
+ IRQF_PERCPU, "ddrc", NULL);
+ if (err) {
+ dev_err(dev,
+ "Busfreq:request_irq failed %d, err = %d\n",
+ irq, err);
+ return err;
+ }
+ err = irq_set_affinity(irq, cpumask_of(cpu));
+ if (err) {
+ dev_err(dev,
+ "Busfreq: Cannot set irq affinity irq=%d\n",
+ irq);
+ return err;
+ }
+ d = irq_get_irq_data(irq);
+ irqs_used[cpu] = d->hwirq + 32;
+ }
+
+ /* Store the variable used to communicate between cores */
+ wait_for_ddr_freq_update = (u32 *)ddr_freq_change_iram_base;
+ imx7_wfe_change_ddr_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base + 0x8,
+ &imx7_smp_wfe, SMP_WFE_CODE_SIZE - 0x8);
+#endif
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ imx7d_change_ddr_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base + SMP_WFE_CODE_SIZE,
+ &imx7d_ddr3_freq_change,
+ MX7_BUSFREQ_OCRAM_SIZE - SMP_WFE_CODE_SIZE);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR3
+ || ddr_type == IMX_DDR_TYPE_LPDDR2)
+ imx7d_change_ddr_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base +
+ SMP_WFE_CODE_SIZE,
+ &imx_lpddr3_freq_change,
+ MX7_BUSFREQ_OCRAM_SIZE - SMP_WFE_CODE_SIZE);
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ return 0;
+}
+
+/* Used by i.MX6SX/i.MX6UL for mmdc setting init. */
+int init_mmdc_ddr3_settings_imx6_up(struct platform_device *busfreq_pdev)
+{
+ int i;
+ struct device_node *node;
+ unsigned long ddr_code_size;
+
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc");
+ if (!node) {
+ printk(KERN_ERR "failed to find mmdc device tree data!\n");
+ return -EINVAL;
+ }
+ mmdc_base = of_iomap(node, 0);
+ WARN(!mmdc_base, "unable to map mmdc registers\n");
+
+ if (cpu_is_imx6sx())
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-iomuxc");
+ else
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-iomuxc");
+ if (!node) {
+ printk(KERN_ERR "failed to find iomuxc device tree data!\n");
+ return -EINVAL;
+ }
+ iomux_base = of_iomap(node, 0);
+ WARN(!iomux_base, "unable to map iomux registers\n");
+
+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6sx) +
+ ARRAY_SIZE(ddr3_calibration_mx6sx);
+
+ normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
+ memcpy(normal_mmdc_settings, ddr3_dll_mx6sx,
+ sizeof(ddr3_dll_mx6sx));
+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6sx)),
+ ddr3_calibration_mx6sx, sizeof(ddr3_calibration_mx6sx));
+
+ /* store the original DDR settings at boot. */
+ for (i = 0; i < ddr_settings_size; i++) {
+ /*
+ * writes via command mode register cannot be read back.
+ * hence hardcode them in the initial static array.
+ * this may require modification on a per customer basis.
+ */
+ if (normal_mmdc_settings[i][0] != 0x1C)
+ normal_mmdc_settings[i][1] =
+ readl_relaxed(mmdc_base
+ + normal_mmdc_settings[i][0]);
+ }
+
+ if (cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz())
+ iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6ul);
+ else
+ iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6sx);
+
+ ddr_code_size = (&imx6_up_ddr3_freq_change_end -&imx6_up_ddr3_freq_change_start) *4 +
+ sizeof(*imx6_busfreq_info);
+ imx6_busfreq_info = (struct imx6_busfreq_info *)ddr_freq_change_iram_base;
+
+ imx6_up_change_ddr_freq = (void *)fncpy((void *)ddr_freq_change_iram_base + sizeof(*imx6_busfreq_info),
+ &imx6_up_ddr3_freq_change, ddr_code_size - sizeof(*imx6_busfreq_info));
+
+ /*
+ * Store the size of the array in iRAM also,
+ * increase the size by 8 bytes.
+ */
+ iram_iomux_settings = (void *)(ddr_freq_change_iram_base + ddr_code_size);
+ iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8;
+
+ if ((ddr_code_size + (iomux_settings_size + ddr_settings_size) * 8 + 16)
+ > ddr_freq_change_total_size) {
+ printk(KERN_ERR "Not enough memory allocated for DDR Frequency change code.\n");
+ return EINVAL;
+ }
+
+ for (i = 0; i < iomux_settings_size; i++) {
+ if (cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz()) {
+ iomux_offsets_mx6ul[i][1] =
+ readl_relaxed(iomux_base +
+ iomux_offsets_mx6ul[i][0]);
+ iram_iomux_settings[i + 1][0] =
+ iomux_offsets_mx6ul[i][0];
+ iram_iomux_settings[i + 1][1] =
+ iomux_offsets_mx6ul[i][1];
+ } else {
+ iomux_offsets_mx6sx[i][1] =
+ readl_relaxed(iomux_base +
+ iomux_offsets_mx6sx[i][0]);
+ iram_iomux_settings[i + 1][0] =
+ iomux_offsets_mx6sx[i][0];
+ iram_iomux_settings[i + 1][1] =
+ iomux_offsets_mx6sx[i][1];
+ }
+ }
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ return 0;
+}
+
+int init_mmdc_ddr3_settings_imx6_smp(struct platform_device *busfreq_pdev)
+{
+ int i;
+ struct device_node *node;
+ unsigned long ddr_code_size;
+ unsigned long wfe_code_size = 0;
+#ifdef CONFIG_SMP
+ u32 cpu;
+ struct device *dev = &busfreq_pdev->dev;
+ int err;
+ struct irq_data *d;
+#endif
+
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine");
+ if (!node) {
+ printk(KERN_ERR "failed to find imx6q-mmdc device tree data!\n");
+ return -EINVAL;
+ }
+ mmdc_base = of_iomap(node, 0);
+ WARN(!mmdc_base, "unable to map mmdc registers\n");
+
+ node = NULL;
+ if (cpu_is_imx6q())
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
+ if (cpu_is_imx6dl())
+ node = of_find_compatible_node(NULL, NULL,
+ "fsl,imx6dl-iomuxc");
+ if (!node) {
+ printk(KERN_ERR "failed to find imx6q-iomux device tree data!\n");
+ return -EINVAL;
+ }
+ iomux_base = of_iomap(node, 0);
+ WARN(!iomux_base, "unable to map iomux registers\n");
+
+ node = NULL;
+ node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
+ if (!node) {
+ printk(KERN_ERR "failed to find imx6q-a9-gic device tree data!\n");
+ return -EINVAL;
+ }
+ gic_dist_base = of_iomap(node, 0);
+ WARN(!gic_dist_base, "unable to map gic dist registers\n");
+
+ if (cpu_is_imx6q())
+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) +
+ ARRAY_SIZE(ddr3_calibration);
+ if (cpu_is_imx6dl())
+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) +
+ ARRAY_SIZE(ddr3_calibration);
+
+ normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
+ if (cpu_is_imx6q()) {
+ memcpy(normal_mmdc_settings, ddr3_dll_mx6q,
+ sizeof(ddr3_dll_mx6q));
+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)),
+ ddr3_calibration, sizeof(ddr3_calibration));
+ }
+ if (cpu_is_imx6dl()) {
+ memcpy(normal_mmdc_settings, ddr3_dll_mx6dl,
+ sizeof(ddr3_dll_mx6dl));
+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)),
+ ddr3_calibration, sizeof(ddr3_calibration));
+ }
+ /* store the original DDR settings at boot. */
+ for (i = 0; i < ddr_settings_size; i++) {
+ /*
+ * writes via command mode register cannot be read back.
+ * hence hardcode them in the initial static array.
+ * this may require modification on a per customer basis.
+ */
+ if (normal_mmdc_settings[i][0] != 0x1C)
+ normal_mmdc_settings[i][1] =
+ readl_relaxed(mmdc_base
+ + normal_mmdc_settings[i][0]);
+ }
+
+#ifdef CONFIG_SMP
+ irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
+ GFP_KERNEL);
+
+ for_each_online_cpu(cpu) {
+ int irq;
+
+ /*
+ * set up a reserved interrupt to get all
+ * the active cores into a WFE state
+ * before changing the DDR frequency.
+ */
+ irq = platform_get_irq(busfreq_pdev, cpu);
+ err = request_irq(irq, wait_in_wfe_irq,
+ IRQF_PERCPU, "mmdc_1", NULL);
+ if (err) {
+ dev_err(dev,
+ "Busfreq:request_irq failed %d, err = %d\n",
+ irq, err);
+ return err;
+ }
+ err = irq_set_affinity(irq, cpumask_of(cpu));
+ if (err) {
+ dev_err(dev,
+ "Busfreq: Cannot set irq affinity irq=%d,\n",
+ irq);
+ return err;
+ }
+ d = irq_get_irq_data(irq);
+ irqs_used[cpu] = d->hwirq + 32;
+ }
+#endif
+ iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
+
+ ddr_code_size = (&mx6_ddr3_freq_change_end -
+ &mx6_ddr3_freq_change_start) * 4;
+
+ mx6_change_ddr_freq = (void *)fncpy((void *)ddr_freq_change_iram_base,
+ &mx6_ddr3_freq_change, ddr_code_size);
+
+ /*
+ * Store the size of the array in iRAM also,
+ * increase the size by 8 bytes.
+ */
+ iram_iomux_settings = (void *)(ddr_freq_change_iram_base +
+ ddr_code_size);
+ iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8;
+#ifdef CONFIG_SMP
+ wfe_freq_change_iram_base = (unsigned long)((u32 *)iram_ddr_settings +
+ (ddr_settings_size * 8) + 8);
+
+ if (wfe_freq_change_iram_base & (FNCPY_ALIGN - 1))
+ wfe_freq_change_iram_base += FNCPY_ALIGN -
+ ((uintptr_t)wfe_freq_change_iram_base % (FNCPY_ALIGN));
+
+ wfe_code_size = (&wfe_smp_freq_change_end -
+ &wfe_smp_freq_change_start) *4;
+
+ wfe_change_ddr_freq = (void *)fncpy((void *)wfe_freq_change_iram_base,
+ &wfe_smp_freq_change, wfe_code_size);
+
+ /*
+ * Store the variable used to communicate
+ * between cores in a non-cacheable IRAM area
+ */
+ wait_for_ddr_freq_update = (u32 *)&iram_iomux_settings[0][1];
+#endif
+
+ if ((ddr_code_size + wfe_code_size + (iomux_settings_size +
+ ddr_settings_size) * 8 + 16)
+ > ddr_freq_change_total_size) {
+ printk(KERN_ERR "Not enough memory for DDR Freq scale.\n");
+ return EINVAL;
+ }
+
+ if (cpu_is_imx6q()) {
+ /* store the IOMUX settings at boot. */
+ for (i = 0; i < iomux_settings_size; i++) {
+ iomux_offsets_mx6q[i][1] =
+ readl_relaxed(iomux_base +
+ iomux_offsets_mx6q[i][0]);
+ iram_iomux_settings[i + 1][0] =
+ iomux_offsets_mx6q[i][0];
+ iram_iomux_settings[i + 1][1] =
+ iomux_offsets_mx6q[i][1];
+ }
+ }
+
+ if (cpu_is_imx6dl()) {
+ for (i = 0; i < iomux_settings_size; i++) {
+ iomux_offsets_mx6dl[i][1] =
+ readl_relaxed(iomux_base +
+ iomux_offsets_mx6dl[i][0]);
+ iram_iomux_settings[i + 1][0] =
+ iomux_offsets_mx6dl[i][0];
+ iram_iomux_settings[i + 1][1] =
+ iomux_offsets_mx6dl[i][1];
+ }
+ }
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/busfreq_lpddr2.c b/arch/arm/mach-imx/busfreq_lpddr2.c
new file mode 100644
index 000000000000..f5b3caa43645
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq_lpddr2.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP.
+ */
+
+/*
+ * 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 busfreq_lpddr2.c
+ *
+ * @brief iMX6 LPDDR2 frequency change specific file.
+ *
+ * @ingroup PM
+ */
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/tlb.h>
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+
+#include "common.h"
+#include "hardware.h"
+
+static struct device *busfreq_dev;
+static int curr_ddr_rate;
+static DEFINE_SPINLOCK(freq_lock);
+
+void (*mx6_change_lpddr2_freq)(u32 ddr_freq, int bus_freq_mode) = NULL;
+
+extern unsigned int ddr_normal_rate;
+extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode);
+extern void imx6_up_lpddr2_freq_change(u32 freq, int bus_freq_mode);
+extern void imx6sll_lpddr2_freq_change(u32 freq, int bus_freq_mode);
+extern unsigned long save_ttbr1(void);
+extern void restore_ttbr1(unsigned long ttbr1);
+extern void mx6q_lpddr2_freq_change(u32 freq, void *ddr_settings);
+extern unsigned long ddr_freq_change_iram_base;
+extern unsigned long imx6_lpddr2_freq_change_start asm("imx6_lpddr2_freq_change_start");
+extern unsigned long imx6_lpddr2_freq_change_end asm("imx6_lpddr2_freq_change_end");
+extern unsigned long mx6q_lpddr2_freq_change_start asm("mx6q_lpddr2_freq_change_start");
+extern unsigned long mx6q_lpddr2_freq_change_end asm("mx6q_lpddr2_freq_change_end");
+extern unsigned long iram_tlb_phys_addr;
+
+struct mmdc_settings_info {
+ u32 size;
+ void *settings;
+ int freq;
+} __aligned(8);
+static struct mmdc_settings_info *mmdc_settings_info;
+void (*mx6_change_lpddr2_freq_smp)(u32 ddr_freq, struct mmdc_settings_info
+ *mmdc_settings_info) = NULL;
+
+static int mmdc_settings_size;
+static unsigned long (*mmdc_settings)[2];
+static unsigned long (*iram_mmdc_settings)[2];
+static unsigned long *iram_settings_size;
+static unsigned long *iram_ddr_freq_chage;
+unsigned long mmdc_timing_settings[][2] = {
+ {0x0C, 0x0}, /* mmdc_mdcfg0 */
+ {0x10, 0x0}, /* mmdc_mdcfg1 */
+ {0x14, 0x0}, /* mmdc_mdcfg2 */
+ {0x18, 0x0}, /* mmdc_mdmisc */
+ {0x38, 0x0}, /* mmdc_mdcfg3lp */
+};
+
+#ifdef CONFIG_SMP
+volatile u32 *wait_for_lpddr2_freq_update;
+static unsigned int online_cpus;
+static u32 *irqs_used;
+void (*wfe_change_lpddr2_freq)(u32 cpuid, u32 *ddr_freq_change_done);
+extern void wfe_smp_freq_change(u32 cpuid, u32 *ddr_freq_change_done);
+extern unsigned long wfe_smp_freq_change_start asm("wfe_smp_freq_change_start");
+extern unsigned long wfe_smp_freq_change_end asm("wfe_smp_freq_change_end");
+extern void __iomem *scu_base;
+static void __iomem *gic_dist_base;
+#endif
+
+#ifdef CONFIG_SMP
+static irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
+{
+ u32 me;
+
+ me = smp_processor_id();
+#ifdef CONFIG_LOCAL_TIMERS
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &me);
+#endif
+ wfe_change_lpddr2_freq(0xff << (me * 8),
+ (u32 *)ddr_freq_change_iram_base);
+#ifdef CONFIG_LOCAL_TIMERS
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &me);
+#endif
+ return IRQ_HANDLED;
+}
+#endif
+
+/* change the DDR frequency. */
+int update_lpddr2_freq(int ddr_rate)
+{
+ unsigned long ttbr1, flags;
+ int mode = get_bus_freq_mode();
+
+ if (ddr_rate == curr_ddr_rate)
+ return 0;
+
+ printk(KERN_DEBUG "\nBus freq set to %d start...\n", ddr_rate);
+
+ spin_lock_irqsave(&freq_lock, flags);
+ /*
+ * Flush the TLB, to ensure no TLB maintenance occurs
+ * when DDR is in self-refresh.
+ */
+ ttbr1 = save_ttbr1();
+
+ /* Now change DDR frequency. */
+ if (cpu_is_imx6sl())
+ mx6_change_lpddr2_freq(ddr_rate,
+ (mode == BUS_FREQ_LOW || mode == BUS_FREQ_ULTRA_LOW) ? 1 : 0);
+ else
+ mx6_change_lpddr2_freq(ddr_rate,
+ (mode == BUS_FREQ_LOW || mode == BUS_FREQ_AUDIO) ? 1 : 0);
+
+ restore_ttbr1(ttbr1);
+
+ curr_ddr_rate = ddr_rate;
+ spin_unlock_irqrestore(&freq_lock, flags);
+
+ printk(KERN_DEBUG "\nBus freq set to %d done...\n", ddr_rate);
+
+ return 0;
+}
+
+int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev)
+{
+ unsigned long ddr_code_size;
+ busfreq_dev = &busfreq_pdev->dev;
+
+ ddr_code_size = SZ_4K;
+
+ if (cpu_is_imx6sl())
+ mx6_change_lpddr2_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base,
+ &mx6_lpddr2_freq_change, ddr_code_size);
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz())
+ mx6_change_lpddr2_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base,
+ &imx6_up_lpddr2_freq_change, ddr_code_size);
+ if (cpu_is_imx6sll())
+ mx6_change_lpddr2_freq = (void *)fncpy(
+ (void *)ddr_freq_change_iram_base,
+ &imx6sll_lpddr2_freq_change, ddr_code_size);
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ return 0;
+}
+
+int update_lpddr2_freq_smp(int ddr_rate)
+{
+ unsigned long ttbr1;
+ int i, me = 0;
+#ifdef CONFIG_SMP
+ int cpu = 0;
+ u32 reg = 0;
+#endif
+
+ if (ddr_rate == curr_ddr_rate)
+ return 0;
+
+ printk(KERN_DEBUG "Bus freq set to %d start...\n", ddr_rate);
+
+ for (i=0; i < mmdc_settings_size; i++) {
+ iram_mmdc_settings[i][0] = mmdc_settings[i][0];
+ iram_mmdc_settings[i][1] = mmdc_settings[i][1];
+ }
+
+ mmdc_settings_info->size = mmdc_settings_size;
+ mmdc_settings_info->settings = iram_mmdc_settings;
+ mmdc_settings_info->freq = curr_ddr_rate;
+
+ /* ensure that all Cores are in WFE. */
+ local_irq_disable();
+
+#ifdef CONFIG_SMP
+ me = smp_processor_id();
+
+ /* Make sure all the online cores are active */
+ while (1) {
+ bool not_exited_busfreq = false;
+ for_each_online_cpu(cpu) {
+ reg = __raw_readl(scu_base + 0x08);
+ if (reg & (0x02 << (cpu * 8)))
+ not_exited_busfreq = true;
+ }
+ if (!not_exited_busfreq)
+ break;
+ }
+
+ wmb();
+ *wait_for_lpddr2_freq_update = 1;
+ dsb();
+ online_cpus = readl_relaxed(scu_base + 0x08);
+ for_each_online_cpu(cpu) {
+ *((char *)(&online_cpus) + (u8)cpu) = 0x02;
+ if (cpu != me) {
+ reg = 1 << (irqs_used[cpu] % 32);
+ writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET
+ + (irqs_used[cpu] / 32) * 4);
+ }
+ }
+
+ /* Wait for the other active CPUs to idle */
+ while (1) {
+ reg = 0;
+ reg = readl_relaxed(scu_base + 0x08);
+ reg |= (0x02 << (me * 8));
+ if (reg == online_cpus)
+ break;
+ }
+#endif
+
+ /* Ensure iram_tlb_phys_addr is flushed to DDR. */
+ __cpuc_flush_dcache_area(&iram_tlb_phys_addr,
+ sizeof(iram_tlb_phys_addr));
+ outer_clean_range(__pa(&iram_tlb_phys_addr),
+ __pa(&iram_tlb_phys_addr + 1));
+ /*
+ * Flush the TLB, to ensure no TLB maintenance occurs
+ * when DDR is in self-refresh.
+ */
+ ttbr1 = save_ttbr1();
+
+ curr_ddr_rate = ddr_rate;
+
+ /* Now change DDR frequency. */
+ mx6_change_lpddr2_freq_smp(ddr_rate, mmdc_settings_info);
+
+ restore_ttbr1(ttbr1);
+
+#ifdef CONFIG_SMP
+ wmb();
+ /* DDR frequency change is done . */
+ *wait_for_lpddr2_freq_update = 0;
+ dsb();
+ /* wake up all the cores. */
+ sev();
+#endif
+
+ local_irq_enable();
+
+ printk(KERN_DEBUG "Bus freq set to %d done! cpu=%d\n", ddr_rate, me);
+
+ return 0;
+}
+
+int init_mmdc_lpddr2_settings_mx6q(struct platform_device *busfreq_pdev)
+{
+ struct device *dev = &busfreq_pdev->dev;
+ unsigned long ddr_code_size = 0;
+ unsigned long wfe_code_size = 0;
+ struct device_node *node;
+ void __iomem *mmdc_base;
+ int i;
+#ifdef CONFIG_SMP
+ struct irq_data *d;
+ u32 cpu;
+ int err;
+#endif
+
+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc");
+ if (!node) {
+ printk(KERN_ERR "failed to find mmdc device tree data!\n");
+ return -EINVAL;
+ }
+
+ mmdc_base = of_iomap(node, 0);
+ if (!mmdc_base) {
+ dev_err(dev, "unable to map mmdc registers\n");
+ return -EINVAL;
+ }
+
+ mmdc_settings_size = ARRAY_SIZE(mmdc_timing_settings);
+ mmdc_settings = kmalloc((mmdc_settings_size * 8), GFP_KERNEL);
+ memcpy(mmdc_settings, mmdc_timing_settings,
+ sizeof(mmdc_timing_settings));
+
+#ifdef CONFIG_SMP
+ node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
+ if (!node) {
+ printk(KERN_ERR "failed to find imx6q-a9-gic device tree data!\n");
+ return -EINVAL;
+ }
+
+ gic_dist_base = of_iomap(node, 0);
+ WARN(!gic_dist_base, "unable to map gic dist registers\n");
+
+ irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
+ GFP_KERNEL);
+
+ for_each_online_cpu(cpu) {
+ int irq = platform_get_irq(busfreq_pdev, cpu);
+ err = request_irq(irq, wait_in_wfe_irq, IRQF_PERCPU,
+ "mmdc_1", NULL);
+ if (err) {
+ dev_err(dev,
+ "Busfreq:request_irq failed %d, err = %d\n",
+ irq, err);
+ return err;
+ }
+ err = irq_set_affinity(irq, cpumask_of(cpu));
+ if (err) {
+ dev_err(dev,
+ "Busfreq: Cannot set irq affinity irq=%d,\n",
+ irq);
+ return err;
+ }
+ d = irq_get_irq_data(irq);
+ irqs_used[cpu] = d->hwirq + 32;
+ }
+
+ /* Stoange_iram_basee the variable used to communicate between cores in
+ * a non-cacheable IRAM area */
+ wait_for_lpddr2_freq_update = (u32 *)ddr_freq_change_iram_base;
+ wfe_code_size = (&wfe_smp_freq_change_end - &wfe_smp_freq_change_start) *4;
+
+ wfe_change_lpddr2_freq = (void *)fncpy((void *)ddr_freq_change_iram_base + 0x8,
+ &wfe_smp_freq_change, wfe_code_size);
+#endif
+ iram_settings_size = (void *)ddr_freq_change_iram_base + wfe_code_size + 0x8;
+ iram_mmdc_settings = (void *)iram_settings_size + sizeof(*mmdc_settings_info);
+ iram_ddr_freq_chage = (void *)iram_mmdc_settings + (mmdc_settings_size * 8) + 0x8;
+ mmdc_settings_info = (struct mmdc_settings_info *)iram_settings_size;
+
+ ddr_code_size = (&mx6q_lpddr2_freq_change_end -&mx6q_lpddr2_freq_change_start) *4;
+
+ mx6_change_lpddr2_freq_smp = (void *)fncpy(iram_ddr_freq_chage,
+ &mx6q_lpddr2_freq_change, ddr_code_size);
+
+ /* save initial mmdc boot timing settings */
+ for (i=0; i < mmdc_settings_size; i++)
+ mmdc_settings[i][1] = readl_relaxed(mmdc_base +
+ mmdc_settings[i][0]);
+
+ curr_ddr_rate = ddr_normal_rate;
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/common.c b/arch/arm/mach-imx/common.c
new file mode 100644
index 000000000000..2f644c6b2c28
--- /dev/null
+++ b/arch/arm/mach-imx/common.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
+ * 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/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_net.h>
+#include <linux/slab.h>
+
+#include "hardware.h"
+
+unsigned long iram_tlb_base_addr;
+unsigned long iram_tlb_phys_addr;
+
+unsigned long save_ttbr1(void)
+{
+ unsigned long lttbr1;
+ asm volatile(
+ ".align 4\n"
+ "mrc p15, 0, %0, c2, c0, 1\n"
+ : "=r" (lttbr1)
+ );
+ return lttbr1;
+}
+
+void restore_ttbr1(unsigned long ttbr1)
+{
+ asm volatile(
+ ".align 4\n"
+ "mcr p15, 0, %0, c2, c0, 1\n"
+ : : "r" (ttbr1)
+ );
+}
+
+#define OCOTP_MAC_OFF (cpu_is_imx7d() ? 0x640 : 0x620)
+#define OCOTP_MACn(n) (OCOTP_MAC_OFF + (n) * 0x10)
+void __init imx6_enet_mac_init(const char *enet_compat, const char *ocotp_compat)
+{
+ struct device_node *ocotp_np, *enet_np, *from = NULL;
+ void __iomem *base;
+ struct property *newmac;
+ u32 macaddr_low;
+ u32 macaddr_high = 0;
+ u32 macaddr1_high = 0;
+ u8 *macaddr;
+ int i, id;
+
+ for (i = 0; i < 2; i++) {
+ enet_np = of_find_compatible_node(from, NULL, enet_compat);
+ if (!enet_np)
+ return;
+
+ from = enet_np;
+
+ if (of_get_mac_address(enet_np))
+ goto put_enet_node;
+
+ id = of_alias_get_id(enet_np, "ethernet");
+ if (id < 0)
+ id = i;
+
+ ocotp_np = of_find_compatible_node(NULL, NULL, ocotp_compat);
+ if (!ocotp_np) {
+ pr_warn("failed to find ocotp node\n");
+ goto put_enet_node;
+ }
+
+ base = of_iomap(ocotp_np, 0);
+ if (!base) {
+ pr_warn("failed to map ocotp\n");
+ goto put_ocotp_node;
+ }
+
+ macaddr_low = readl_relaxed(base + OCOTP_MACn(1));
+ if (id)
+ macaddr1_high = readl_relaxed(base + OCOTP_MACn(2));
+ else
+ macaddr_high = readl_relaxed(base + OCOTP_MACn(0));
+
+ newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
+ if (!newmac)
+ goto put_ocotp_node;
+
+ newmac->value = newmac + 1;
+ newmac->length = 6;
+ newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
+ if (!newmac->name) {
+ kfree(newmac);
+ goto put_ocotp_node;
+ }
+
+ macaddr = newmac->value;
+ if (id) {
+ macaddr[5] = (macaddr_low >> 16) & 0xff;
+ macaddr[4] = (macaddr_low >> 24) & 0xff;
+ macaddr[3] = macaddr1_high & 0xff;
+ macaddr[2] = (macaddr1_high >> 8) & 0xff;
+ macaddr[1] = (macaddr1_high >> 16) & 0xff;
+ macaddr[0] = (macaddr1_high >> 24) & 0xff;
+ } else {
+ macaddr[5] = macaddr_high & 0xff;
+ macaddr[4] = (macaddr_high >> 8) & 0xff;
+ macaddr[3] = (macaddr_high >> 16) & 0xff;
+ macaddr[2] = (macaddr_high >> 24) & 0xff;
+ macaddr[1] = macaddr_low & 0xff;
+ macaddr[0] = (macaddr_low >> 8) & 0xff;
+ }
+
+ of_update_property(enet_np, newmac);
+
+put_ocotp_node:
+ of_node_put(ocotp_np);
+put_enet_node:
+ of_node_put(enet_np);
+ }
+}
+
+#ifndef CONFIG_HAVE_IMX_GPC
+int imx_gpc_mf_request_on(unsigned int irq, unsigned int on) { return 0; }
+EXPORT_SYMBOL_GPL(imx_gpc_mf_request_on);
+#endif
+
+#if !defined(CONFIG_SOC_IMX6SL)
+u32 imx6_lpddr2_freq_change_start, imx6_lpddr2_freq_change_end;
+void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode) {}
+#endif
+
+#if !defined(CONFIG_SOC_IMX6SLL)
+void imx6sll_lpddr2_freq_change(u32 freq, int bus_freq_mode) {}
+#endif
+
+#if !defined(CONFIG_SOC_IMX6SX) && !defined(CONFIG_SOC_IMX6UL)
+u32 imx6_up_ddr3_freq_change_start, imx6_up_ddr3_freq_change_end;
+struct imx6_busfreq_info {
+} __aligned(8);
+void imx6_up_ddr3_freq_change(struct imx6_busfreq_info *busfreq_info) {}
+void imx6_up_lpddr2_freq_change(u32 freq, int bus_freq_mode) {}
+#endif
+
+#if !defined(CONFIG_SOC_IMX6Q)
+u32 mx6_ddr3_freq_change_start, mx6_ddr3_freq_change_end;
+u32 mx6q_lpddr2_freq_change_start, mx6q_lpddr2_freq_change_end;
+u32 wfe_smp_freq_change_start, wfe_smp_freq_change_end;
+void mx6_ddr3_freq_change(u32 freq, void *ddr_settings,
+ bool dll_mode, void *iomux_offsets) {}
+void mx6q_lpddr2_freq_change(u32 freq, void *ddr_settings) {}
+void wfe_smp_freq_change(u32 cpuid, u32 *ddr_freq_change_done) {}
+#endif
+
+#if !defined(CONFIG_SOC_IMX7D)
+void imx7_smp_wfe(u32 cpuid, u32 ocram_base) {}
+void imx7d_ddr3_freq_change(u32 freq) {}
+#endif
+
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 5aa5796cff0e..303df4381ded 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -8,6 +8,7 @@
#define __ASM_ARCH_MXC_COMMON_H__
#include <linux/reboot.h>
+#include <soc/imx/src.h>
struct irq_data;
struct platform_device;
@@ -56,9 +57,19 @@ void imx_gpc_set_arm_power_in_lpm(bool power_off);
void imx_gpc_set_l2_mem_power_in_lpm(bool power_off);
void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
+void imx_gpcv2_pre_suspend(bool arm_power_off);
+void imx_gpcv2_post_resume(void);
+unsigned int imx_gpcv2_is_mf_mix_off(void);
+void imx_gpcv2_enable_wakeup_for_m4(void);
+void imx_gpcv2_disable_wakeup_for_m4(void);
void imx25_pm_init(void);
void imx27_pm_init(void);
void imx5_pmu_init(void);
+#ifdef CONFIG_HAVE_IMX_MU
+int imx_mu_lpm_ready(bool ready);
+#else
+static inline int imx_mu_lpm_ready(bool ready) { return 0; }
+#endif
enum mxc_cpu_pwr_mode {
WAIT_CLOCKED, /* wfi only */
@@ -89,33 +100,97 @@ void imx_smp_prepare(void);
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
+void imx6sx_set_m4_highfreq(bool high_freq);
+void imx_mu_enable_m4_irqs_in_gic(bool enable);
+#ifdef CONFIG_HAVE_IMX_GPC
+void imx_gpc_add_m4_wake_up_irq(u32 irq, bool enable);
+unsigned int imx_gpc_is_m4_sleeping(void);
+#else
+static inline void imx_gpc_add_m4_wake_up_irq(u32 irq, bool enable) {}
+static inline unsigned int imx_gpc_is_m4_sleeping(void) { return 0; }
+#endif
+#ifdef CONFIG_HAVE_IMX_GPCV2
+int imx_gpcv2_mf_power_on(unsigned int irq, unsigned int on);
+void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
+void imx_gpcv2_add_m4_wake_up_irq(u32 hwirq, bool enable);
+#else
+static inline int imx_gpcv2_mf_power_on(unsigned int irq, unsigned int on) { return 0; }
+static inline void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn) {}
+static inline void imx_gpcv2_add_m4_wake_up_irq(u32 hwirq, bool enable) {}
+#endif
+void imx_gpc_hold_m4_in_sleep(void);
+void imx_gpc_release_m4_in_sleep(void);
+void __init imx_gpcv2_check_dt(void);
+void imx_gpcv2_set_lpm_mode(enum mxc_cpu_pwr_mode mode);
+void imx_gpcv2_set_cpu_power_gate_in_idle(bool pdn);
+void imx_gpcv2_enable_rbc(bool enable);
+bool imx_mu_is_m4_in_low_freq(void);
+bool imx_mu_is_m4_in_stop(void);
+void imx_mu_set_m4_run_mode(void);
void imx_src_init(void);
void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
+void imx_gpc_switch_pupscr_clk(bool flag);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
void imx_gpc_hwirq_mask(unsigned int hwirq);
void imx_gpc_hwirq_unmask(unsigned int hwirq);
+unsigned int imx_gpc_is_mf_mix_off(void);
void imx_anatop_init(void);
void imx_anatop_pre_suspend(void);
void imx_anatop_post_resume(void);
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
+void imx6_enet_mac_init(const char *enet_compat, const char *ocotp_compat);
+void imx6sl_low_power_idle(void);
+void imx6sll_low_power_idle(void);
+void imx6sx_low_power_idle(void);
+void imx6ul_low_power_idle(void);
+void imx6ull_low_power_idle(void);
+void imx7d_low_power_idle(void);
+#ifdef CONFIG_HAVE_IMX_MMDC
int imx_mmdc_get_ddr_type(void);
+int imx_mmdc_get_lpddr2_2ch_mode(void);
+#else
+static inline int imx_mmdc_get_ddr_type(void) { return 0; }
+static inline int imx_mmdc_get_lpddr2_2ch_mode(void) { return 0; }
+#endif
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
+void imx_busfreq_map_io(void);
+void imx7_pm_map_io(void);
+void imx6_pm_map_io(void);
+void imx7ulp_pm_map_io(void);
+void imx7ulp_enable_nmi(void);
+void imx7ulp_poweroff(void);
void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
#ifdef CONFIG_SUSPEND
+void v7_cpu_resume(void);
+void ca7_cpu_resume(void);
void imx53_suspend(void __iomem *ocram_vbase);
extern const u32 imx53_suspend_sz;
void imx6_suspend(void __iomem *ocram_vbase);
+void imx7_suspend(void __iomem *ocram_vbase);
+void imx7ulp_cpu_resume(void);
+void imx7ulp_suspend(void __iomem *ocram_vbase);
#else
+static inline void v7_cpu_resume(void) {}
+static inline void ca7_cpu_resume(void) {}
static inline void imx53_suspend(void __iomem *ocram_vbase) {}
static const u32 imx53_suspend_sz;
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
+static inline void imx7_suspend(void __iomem *ocram_vbase) {}
+static inline void imx7ulp_cpu_resume(void) {}
+static inline void imx7ulp_suspend(void __iomem *ocram_vbase) {}
+#endif
+
+#ifdef CONFIG_HAVE_IMX_DDRC
+int imx_ddrc_get_ddr_type(void);
+#else
+static inline int imx_ddrc_get_ddr_type(void) { return 0; }
#endif
void v7_cpu_resume(void);
@@ -126,6 +201,7 @@ void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6ul_pm_init(void);
+void imx7d_pm_init(void);
void imx7ulp_pm_init(void);
#ifdef CONFIG_PM
@@ -151,4 +227,5 @@ static inline void imx_init_l2cache(void) {}
extern const struct smp_operations imx_smp_ops;
extern const struct smp_operations ls1021a_smp_ops;
+extern bool uart_from_osc;
#endif
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 0b137eeffb61..cd83ca08826e 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -1,15 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/err.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include "hardware.h"
#include "common.h"
+#define OCOTP_UID_H 0x420
+#define OCOTP_UID_L 0x410
+
unsigned int __mxc_cpu_type;
static unsigned int imx_soc_revision;
@@ -76,9 +81,13 @@ void __init imx_aips_allow_unprivileged_access(
struct device * __init imx_soc_device_init(void)
{
struct soc_device_attribute *soc_dev_attr;
+ const char *ocotp_compat = NULL;
struct soc_device *soc_dev;
struct device_node *root;
+ struct regmap *ocotp = NULL;
const char *soc_id;
+ u64 soc_uid = 0;
+ u32 val;
int ret;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -119,30 +128,42 @@ struct device * __init imx_soc_device_init(void)
soc_id = "i.MX53";
break;
case MXC_CPU_IMX6SL:
+ ocotp_compat = "fsl,imx6sl-ocotp";
soc_id = "i.MX6SL";
break;
case MXC_CPU_IMX6DL:
+ ocotp_compat = "fsl,imx6q-ocotp";
soc_id = "i.MX6DL";
break;
case MXC_CPU_IMX6SX:
+ ocotp_compat = "fsl,imx6sx-ocotp";
soc_id = "i.MX6SX";
break;
case MXC_CPU_IMX6Q:
- soc_id = "i.MX6Q";
+ ocotp_compat = "fsl,imx6q-ocotp";
+ if (imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ soc_id = "i.MX6QP";
+ else
+ soc_id = "i.MX6Q";
break;
case MXC_CPU_IMX6UL:
+ ocotp_compat = "fsl,imx6ul-ocotp";
soc_id = "i.MX6UL";
break;
case MXC_CPU_IMX6ULL:
+ ocotp_compat = "fsl,imx6ull-ocotp";
soc_id = "i.MX6ULL";
break;
case MXC_CPU_IMX6ULZ:
+ ocotp_compat = "fsl,imx6ull-ocotp";
soc_id = "i.MX6ULZ";
break;
case MXC_CPU_IMX6SLL:
+ ocotp_compat = "fsl,imx6sll-ocotp";
soc_id = "i.MX6SLL";
break;
case MXC_CPU_IMX7D:
+ ocotp_compat = "fsl,imx7d-ocotp";
soc_id = "i.MX7D";
break;
case MXC_CPU_IMX7ULP:
@@ -153,18 +174,38 @@ struct device * __init imx_soc_device_init(void)
}
soc_dev_attr->soc_id = soc_id;
+ if (ocotp_compat) {
+ ocotp = syscon_regmap_lookup_by_compatible(ocotp_compat);
+ if (IS_ERR(ocotp))
+ pr_err("%s: failed to find %s regmap!\n", __func__, ocotp_compat);
+ }
+
+ if (!IS_ERR_OR_NULL(ocotp)) {
+ regmap_read(ocotp, OCOTP_UID_H, &val);
+ soc_uid = val;
+ regmap_read(ocotp, OCOTP_UID_L, &val);
+ soc_uid <<= 32;
+ soc_uid |= val;
+ }
+
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
(imx_soc_revision >> 4) & 0xf,
imx_soc_revision & 0xf);
if (!soc_dev_attr->revision)
goto free_soc;
+ soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
+ if (!soc_dev_attr->serial_number)
+ goto free_rev;
+
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev))
- goto free_rev;
+ goto free_serial_number;
return soc_device_to_device(soc_dev);
+free_serial_number:
+ kfree(soc_dev_attr->serial_number);
free_rev:
kfree(soc_dev_attr->revision);
free_soc:
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index 4521e5352bf6..e54acc2ac8a1 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -1,26 +1,104 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
*/
+#include <linux/busfreq-imx.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/psci.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
#include <asm/cpuidle.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+
+#include <uapi/linux/psci.h>
#include "common.h"
#include "cpuidle.h"
+#include "hardware.h"
+
+#define MAX_MMDC_IO_NUM 19
+
+static void __iomem *wfi_iram_base;
+extern unsigned long iram_tlb_base_addr;
+
+#ifdef CONFIG_CPU_FREQ
+extern unsigned long mx6sl_lpm_wfi_start asm("mx6sl_lpm_wfi_start");
+extern unsigned long mx6sl_lpm_wfi_end asm("mx6sl_lpm_wfi_end");
+#endif
+
+struct imx6_cpuidle_pm_info {
+ u32 pm_info_size; /* Size of pm_info */
+ u32 ttbr;
+ void __iomem *mmdc_base;
+ void __iomem *iomuxc_base;
+ void __iomem *ccm_base;
+ void __iomem *l2_base;
+ void __iomem *anatop_base;
+ u32 mmdc_io_num; /*Number of MMDC IOs which need saved/restored. */
+ u32 mmdc_io_val[MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+static const u32 imx6sl_mmdc_io_offset[] __initconst = {
+ 0x30c, 0x310, 0x314, 0x318, /* DQM0 ~ DQM3 */
+ 0x5c4, 0x5cc, 0x5d4, 0x5d8, /* GPR_B0DS ~ GPR_B3DS */
+ 0x300, 0x31c, 0x338, 0x5ac, /*CAS, RAS, SDCLK_0, GPR_ADDS */
+ 0x33c, 0x340, 0x5b0, 0x5c0, /*SODT0, SODT1, ,MODE_CTL, MODE */
+ 0x330, 0x334, 0x320, /*SDCKE0, SDCK1, RESET */
+};
+
+static struct regulator *vbus_ldo;
+static struct regulator_dev *ldo2p5_dummy_regulator_rdev;
+static struct regulator_init_data ldo2p5_dummy_initdata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+static int ldo2p5_dummy_enable;
+
+static void (*imx6sl_wfi_in_iram_fn)(void __iomem *iram_vbase,
+ int audio_mode, bool vbus_ldo);
+
+#define MX6SL_POWERDWN_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
static int imx6sl_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
+ int mode = get_bus_freq_mode();
+
imx6_set_lpm(WAIT_UNCLOCKED);
- /*
- * Software workaround for ERR005311, see function
- * description for details.
- */
- imx6sl_set_wait_clk(true);
- cpu_do_idle();
- imx6sl_set_wait_clk(false);
+
+ if ((mode == BUS_FREQ_AUDIO) || (mode == BUS_FREQ_ULTRA_LOW)) {
+ /*
+ * bit 2 used for low power mode;
+ * bit 1 used for the ldo2p5_dummmy enable
+ */
+ if (psci_ops.cpu_suspend) {
+ psci_ops.cpu_suspend((MX6SL_POWERDWN_IDLE_PARAM | ((mode == BUS_FREQ_AUDIO ? 1 : 0) << 2) |
+ (ldo2p5_dummy_enable ? 1 : 0) << 1), __pa(cpu_resume));
+ } else {
+ imx6sl_wfi_in_iram_fn(wfi_iram_base, (mode == BUS_FREQ_AUDIO) ? 1 : 0,
+ ldo2p5_dummy_enable);
+ }
+ } else {
+ /*
+ * Software workaround for ERR005311, see function
+ * description for details.
+ */
+ imx6sl_set_wait_clk(true);
+ cpu_do_idle();
+ imx6sl_set_wait_clk(false);
+ }
imx6_set_lpm(WAIT_CLOCKED);
return index;
@@ -48,5 +126,109 @@ static struct cpuidle_driver imx6sl_cpuidle_driver = {
int __init imx6sl_cpuidle_init(void)
{
+
+#ifdef CONFIG_CPU_FREQ
+ struct imx6_cpuidle_pm_info *pm_info;
+ int i;
+ const u32 *mmdc_offset_array;
+ u32 wfi_code_size;
+
+ vbus_ldo = regulator_get(NULL, "ldo2p5-dummy");
+ if (IS_ERR(vbus_ldo))
+ vbus_ldo = NULL;
+
+ wfi_iram_base = (void *)(iram_tlb_base_addr + MX6_CPUIDLE_IRAM_ADDR_OFFSET);
+
+ /* Make sure wif_iram_base is 8 byte aligned. */
+ if ((uintptr_t)(wfi_iram_base) & (FNCPY_ALIGN - 1))
+ wfi_iram_base += FNCPY_ALIGN - ((uintptr_t)wfi_iram_base % (FNCPY_ALIGN));
+
+ pm_info = wfi_iram_base;
+ pm_info->pm_info_size = sizeof(*pm_info);
+ pm_info->mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset);
+ mmdc_offset_array = imx6sl_mmdc_io_offset;
+ pm_info->mmdc_base = (void __iomem *)IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR);
+ pm_info->ccm_base = (void __iomem *)IMX_IO_P2V(MX6Q_CCM_BASE_ADDR);
+ pm_info->anatop_base = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+ pm_info->iomuxc_base = (void __iomem *)IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR);
+ pm_info->l2_base = (void __iomem *)IMX_IO_P2V(MX6Q_L2_BASE_ADDR);
+
+ /* Only save mmdc io offset, settings will be saved in asm code */
+ for (i = 0; i < pm_info->mmdc_io_num; i++)
+ pm_info->mmdc_io_val[i][0] = mmdc_offset_array[i];
+
+ /* calculate the wfi code size */
+ wfi_code_size = (&mx6sl_lpm_wfi_end -&mx6sl_lpm_wfi_start) *4;
+
+ imx6sl_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base + sizeof(*pm_info),
+ &imx6sl_low_power_idle, wfi_code_size);
+#endif
+
return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
}
+
+static int imx_ldo2p5_dummy_enable(struct regulator_dev *rdev)
+{
+ ldo2p5_dummy_enable = 1;
+ return 0;
+}
+
+static int imx_ldo2p5_dummy_disable(struct regulator_dev *rdev)
+{
+ ldo2p5_dummy_enable = 0;
+ return 0;
+}
+
+static int imx_ldo2p5_dummy_is_enable(struct regulator_dev *rdev)
+{
+ return ldo2p5_dummy_enable;
+}
+
+static struct regulator_ops ldo2p5_dummy_ops = {
+ .enable = imx_ldo2p5_dummy_enable,
+ .disable = imx_ldo2p5_dummy_disable,
+ .is_enabled = imx_ldo2p5_dummy_is_enable,
+};
+
+static struct regulator_desc ldo2p5_dummy_desc = {
+ .name = "ldo2p5-dummy",
+ .id = -1,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .ops = &ldo2p5_dummy_ops,
+};
+
+static int ldo2p5_dummy_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = { };
+ int ret;
+
+ config.dev = &pdev->dev;
+ config.init_data = &ldo2p5_dummy_initdata;
+ config.of_node = pdev->dev.of_node;
+
+ ldo2p5_dummy_regulator_rdev = regulator_register(&ldo2p5_dummy_desc, &config);
+ if (IS_ERR(ldo2p5_dummy_regulator_rdev)) {
+ ret = PTR_ERR(ldo2p5_dummy_regulator_rdev);
+ dev_err(&pdev->dev, "Failed to register dummy ldo2p5 regulator: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static const struct of_device_id imx_ldo2p5_dummy_ids[] = {
+ { .compatible = "fsl,imx6-dummy-ldo2p5", },
+ { },
+};
+MODULE_DEVICE_TABLE(ofm, imx_ldo2p5_dummy_ids);
+
+static struct platform_driver ldo2p5_dummy_driver = {
+ .probe = ldo2p5_dummy_probe,
+ .driver = {
+ .name = "ldo2p5-dummy",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_ldo2p5_dummy_ids,
+ },
+};
+
+module_platform_driver(ldo2p5_dummy_driver);
diff --git a/arch/arm/mach-imx/cpuidle-imx6sll.c b/arch/arm/mach-imx/cpuidle-imx6sll.c
new file mode 100644
index 000000000000..bb8678ff56f0
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sll.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP.
+ *
+ * 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/busfreq-imx.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/psci.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <asm/cpuidle.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include <uapi/linux/psci.h>
+
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+#define MAX_MMDC_IO_NUM 14
+
+#define PMU_LOW_PWR_CTRL 0x270
+#define XTALOSC24M_OSC_CONFIG0 0x2a0
+#define XTALOSC24M_OSC_CONFIG1 0x2b0
+#define XTALOSC24M_OSC_CONFIG2 0x2c0
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT 24
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT 16
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT 12
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT 4
+#define XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT 1
+#define XTALOSC24M_OSC_CONFIG0_START_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT 20
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK 0xfff
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT 0
+
+extern unsigned long iram_tlb_phys_addr;
+static void __iomem *wfi_iram_base;
+
+#ifdef CONFIG_CPU_FREQ
+static void __iomem *wfi_iram_base_phys;
+extern unsigned long mx6sll_lpm_wfi_start asm("mx6sll_lpm_wfi_start");
+extern unsigned long mx6sll_lpm_wfi_end asm("mx6sll_lpm_wfi_end");
+#endif
+
+struct imx6_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+struct imx6_cpuidle_pm_info {
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 pm_info_size; /* Size of pm_info. */
+ u32 ttbr;
+ struct imx6_pm_base mmdc_base;
+ struct imx6_pm_base iomuxc_base;
+ struct imx6_pm_base ccm_base;
+ struct imx6_pm_base gpc_base;
+ struct imx6_pm_base anatop_base;
+ struct imx6_pm_base src_base;
+ struct imx6_pm_base l2_base;
+ u32 saved_diagnostic; /* To save disagnostic register */
+ u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
+ u32 mmdc_io_val[MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+static const u32 imx6sll_mmdc_io_offset[] __initconst = {
+ 0x294, 0x298, 0x29c, 0x2a0, /* DQM0, DQM1, RAS, CAS */
+ 0x544, 0x54c, 0x554, 0x558, /* GPR_B0DS ~ GPR_B3DS */
+ 0x530, 0x540, 0x2ac, 0x52c, /* MODE_CTL, MODE, SDCLK0, GPR_ADDS */
+ 0x2a4, 0x2a8, /* SDCKE0, SDCKE1 */
+};
+
+static void (*imx6sll_wfi_in_iram_fn)(void __iomem *iram_vbase);
+
+#define MX6SLL_POWERDWN_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+static int imx6sll_idle_finish(unsigned long val)
+{
+ if (psci_ops.cpu_suspend)
+ psci_ops.cpu_suspend(MX6SLL_POWERDWN_IDLE_PARAM,
+ __pa(cpu_resume));
+ else
+ imx6sll_wfi_in_iram_fn(wfi_iram_base);
+
+ return 0;
+}
+
+static int imx6sll_enter_wait(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ int mode = get_bus_freq_mode();
+
+ imx6_set_lpm(WAIT_UNCLOCKED);
+ if ((index == 1) || ((mode != BUS_FREQ_LOW) && index == 2)) {
+ index = 1;
+ cpu_do_idle();
+ } else {
+ imx_gpc_switch_pupscr_clk(true);
+ /* Need to notify there is a cpu pm operation. */
+ cpu_pm_enter();
+ cpu_cluster_pm_enter();
+
+ cpu_suspend(0, imx6sll_idle_finish);
+
+ cpu_cluster_pm_exit();
+ cpu_pm_exit();
+ imx6_enable_rbc(false);
+
+ imx_gpc_switch_pupscr_clk(false);
+ }
+
+ imx6_set_lpm(WAIT_CLOCKED);
+
+ return index;
+}
+
+static struct cpuidle_driver imx6sll_cpuidle_driver = {
+ .name = "imx6sll_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .enter = imx6sll_enter_wait,
+ .name = "WAIT",
+ .desc = "Clock off",
+ },
+ /* LOW POWER IDLE */
+ {
+ /*
+ * RBC 130us + ARM gating 43us + RBC clear 65us
+ * + PLL2 relock 450us and some margin, here set
+ * it to 700us.
+ */
+ .exit_latency = 700,
+ .target_residency = 1000,
+ .enter = imx6sll_enter_wait,
+ .name = "LOW-POWER-IDLE",
+ .desc = "ARM power off",
+ }
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int __init imx6sll_cpuidle_init(void)
+{
+ void __iomem *anatop_base = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+ u32 val;
+#ifdef CONFIG_CPU_FREQ
+ struct imx6_cpuidle_pm_info *cpuidle_pm_info;
+ int i;
+ const u32 *mmdc_offset_array;
+ u32 wfi_code_size;
+
+ wfi_iram_base_phys = (void *)(iram_tlb_phys_addr + MX6_CPUIDLE_IRAM_ADDR_OFFSET);
+
+ /* Make sure wfi_iram_base is 8 byte aligned. */
+ if ((uintptr_t)(wfi_iram_base_phys) & (FNCPY_ALIGN - 1))
+ wfi_iram_base_phys += FNCPY_ALIGN - ((uintptr_t)wfi_iram_base_phys % (FNCPY_ALIGN));
+
+ wfi_iram_base = (void *)IMX_IO_P2V((unsigned long) wfi_iram_base_phys);
+
+ cpuidle_pm_info = wfi_iram_base;
+ cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
+ cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
+ cpuidle_pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
+ cpuidle_pm_info->mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset);
+ mmdc_offset_array = imx6sll_mmdc_io_offset;
+
+ cpuidle_pm_info->mmdc_base.pbase = MX6Q_MMDC_P0_BASE_ADDR;
+ cpuidle_pm_info->mmdc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR);
+
+ cpuidle_pm_info->ccm_base.pbase = MX6Q_CCM_BASE_ADDR;
+ cpuidle_pm_info->ccm_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_CCM_BASE_ADDR);
+
+ cpuidle_pm_info->anatop_base.pbase = MX6Q_ANATOP_BASE_ADDR;
+ cpuidle_pm_info->anatop_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+
+ cpuidle_pm_info->gpc_base.pbase = MX6Q_GPC_BASE_ADDR;
+ cpuidle_pm_info->gpc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_GPC_BASE_ADDR);
+
+ cpuidle_pm_info->iomuxc_base.pbase = MX6Q_IOMUXC_BASE_ADDR;
+ cpuidle_pm_info->iomuxc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR);
+
+ cpuidle_pm_info->src_base.pbase = MX6Q_SRC_BASE_ADDR;
+ cpuidle_pm_info->src_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_SRC_BASE_ADDR);
+
+ cpuidle_pm_info->l2_base.pbase = MX6Q_L2_BASE_ADDR;
+ cpuidle_pm_info->l2_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_L2_BASE_ADDR);
+
+ /* Only save mmdc io offset, settings will be saved in asm code */
+ for (i = 0; i < cpuidle_pm_info->mmdc_io_num; i++)
+ cpuidle_pm_info->mmdc_io_val[i][0] = mmdc_offset_array[i];
+
+ wfi_code_size = (&mx6sll_lpm_wfi_end -&mx6sll_lpm_wfi_start) *4;
+
+ imx6sll_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base + sizeof(*cpuidle_pm_info),
+ &imx6sll_low_power_idle, wfi_code_size);
+#endif
+
+ imx6_set_int_mem_clk_lpm(true);
+
+ /*
+ * enable RC-OSC here, as it needs at least 4ms for RC-OSC to
+ * be stable, low power idle flow can NOT endure this big
+ * latency, so we make RC-OSC self-tuning enabled here.
+ */
+ val = readl_relaxed(anatop_base + PMU_LOW_PWR_CTRL);
+ val |= 0x1;
+ writel_relaxed(val, anatop_base + PMU_LOW_PWR_CTRL);
+ /*
+ * config RC-OSC freq
+ * tune_enable = 1;tune_start = 1;hyst_plus = 0;hyst_minus = 0;
+ * osc_prog = 0xa7;
+ */
+ writel_relaxed(
+ 0x4 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT |
+ 0xa7 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_START_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set count_trg = 0x2dc */
+ writel_relaxed(
+ 0x40 << XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT |
+ 0x2dc << XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG1);
+ /* wait 4ms according to hardware design */
+ msleep(4);
+ /*
+ * now add some hysteresis, hyst_plus=3, hyst_minus=3
+ * (the minimum hysteresis that looks good is 2)
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG0);
+ val &= ~((XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT));
+ val |= (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set the count_1m_trg = 0x2d7 */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG2);
+ val &= ~(XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK <<
+ XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT);
+ val |= 0x2d7 << XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT;
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG2);
+ /*
+ * hardware design require to write XTALOSC24M_OSC_CONFIG0 or
+ * XTALOSC24M_OSC_CONFIG1 to
+ * make XTALOSC24M_OSC_CONFIG2 write work
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG1);
+
+ return cpuidle_register(&imx6sll_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
index 74ea1720e3d8..692775a223a2 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sx.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -1,20 +1,97 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
*/
+#include <linux/busfreq-imx.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/psci.h>
#include <asm/cacheflush.h>
#include <asm/cpuidle.h>
+#include <asm/fncpy.h>
+#include <asm/mach/map.h>
+#include <asm/proc-fns.h>
#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include <uapi/linux/psci.h>
#include "common.h"
#include "cpuidle.h"
#include "hardware.h"
-static int imx6sx_idle_finish(unsigned long val)
+#define MX6_MAX_MMDC_IO_NUM 19
+
+#define PMU_LOW_PWR_CTRL 0x270
+#define XTALOSC24M_OSC_CONFIG0 0x2a0
+#define XTALOSC24M_OSC_CONFIG1 0x2b0
+#define XTALOSC24M_OSC_CONFIG2 0x2c0
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT 24
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT 16
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT 12
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT 4
+#define XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT 1
+#define XTALOSC24M_OSC_CONFIG0_START_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT 20
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK 0xfff
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT 0
+
+extern unsigned long iram_tlb_phys_addr;
+
+static void __iomem *wfi_iram_base;
+#ifdef CONFIG_CPU_FREQ
+static void __iomem *wfi_iram_base_phys;
+extern unsigned long mx6sx_lpm_wfi_start asm("mx6sx_lpm_wfi_start");
+extern unsigned long mx6sx_lpm_wfi_end asm("mx6sx_lpm_wfi_end");
+#endif
+
+struct imx6_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+static const u32 imx6sx_mmdc_io_offset[] __initconst = {
+ 0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
+ 0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
+ 0x60c, 0x610, 0x61c, 0x620, /* B0DS ~ B3DS */
+ 0x5f8, 0x608, 0x310, 0x314, /* CTL, MODE, SODT0, SODT1 */
+ 0x300, 0x2fc, 0x32c, /* CAS, RAS, SDCLK_0 */
+};
+
+struct imx6_cpuidle_pm_info {
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 pm_info_size; /* Size of pm_info. */
+ u32 ttbr;
+ struct imx6_pm_base mmdc_base;
+ struct imx6_pm_base iomuxc_base;
+ struct imx6_pm_base ccm_base;
+ struct imx6_pm_base gpc_base;
+ struct imx6_pm_base l2_base;
+ struct imx6_pm_base anatop_base;
+ struct imx6_pm_base src_base;
+ struct imx6_pm_base sema4_base;
+ u32 saved_diagnostic; /* To save disagnostic register */
+ u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
+ u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+static void (*imx6sx_wfi_in_iram_fn)(void __iomem *iram_vbase);
+
+#define MX6SX_POWERDWN_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+static int imx6_idle_finish(unsigned long val)
{
/*
* for Cortex-A7 which has an internal L2
@@ -25,7 +102,11 @@ static int imx6sx_idle_finish(unsigned long val)
* just call flush_cache_all() is fine.
*/
flush_cache_all();
- cpu_do_idle();
+ if (psci_ops.cpu_suspend)
+ psci_ops.cpu_suspend(MX6SX_POWERDWN_IDLE_PARAM,
+ __pa(cpu_resume));
+ else
+ imx6sx_wfi_in_iram_fn(wfi_iram_base);
return 0;
}
@@ -33,29 +114,22 @@ static int imx6sx_idle_finish(unsigned long val)
static int imx6sx_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- imx6_set_lpm(WAIT_UNCLOCKED);
+ int mode = get_bus_freq_mode();
- switch (index) {
- case 1:
+ imx6_set_lpm(WAIT_UNCLOCKED);
+ if ((index == 1) || ((mode != BUS_FREQ_LOW) && index == 2)) {
+ index = 1;
cpu_do_idle();
- break;
- case 2:
- imx6_enable_rbc(true);
- imx_gpc_set_arm_power_in_lpm(true);
- imx_set_cpu_jump(0, v7_cpu_resume);
- /* Need to notify there is a cpu pm operation. */
- cpu_pm_enter();
- cpu_cluster_pm_enter();
-
- cpu_suspend(0, imx6sx_idle_finish);
-
- cpu_cluster_pm_exit();
- cpu_pm_exit();
- imx_gpc_set_arm_power_in_lpm(false);
- imx6_enable_rbc(false);
- break;
- default:
- break;
+ } else {
+ /* Need to notify there is a cpu pm operation. */
+ cpu_pm_enter();
+ cpu_cluster_pm_enter();
+
+ cpu_suspend(0, imx6_idle_finish);
+
+ cpu_cluster_pm_exit();
+ cpu_pm_exit();
+ imx6_enable_rbc(false);
}
imx6_set_lpm(WAIT_CLOCKED);
@@ -69,25 +143,23 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = {
.states = {
/* WFI */
ARM_CPUIDLE_WFI_STATE,
- /* WAIT */
+ /* WAIT MODE */
{
.exit_latency = 50,
.target_residency = 75,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
.enter = imx6sx_enter_wait,
.name = "WAIT",
.desc = "Clock off",
},
- /* WAIT + ARM power off */
+ /* LOW POWER IDLE */
{
/*
- * ARM gating 31us * 5 + RBC clear 65us
- * and some margin for SW execution, here set it
- * to 300us.
+ * RBC 130us + ARM gating 93us + RBC clear 65us
+ * + PLL2 relock 450us and some margin, here set
+ * it to 800us.
*/
- .exit_latency = 300,
- .target_residency = 500,
- .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .exit_latency = 800,
+ .target_residency = 1000,
.enter = imx6sx_enter_wait,
.name = "LOW-POWER-IDLE",
.desc = "ARM power off",
@@ -99,17 +171,119 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = {
int __init imx6sx_cpuidle_init(void)
{
+ void __iomem *anatop_base = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+ u32 val;
+#ifdef CONFIG_CPU_FREQ
+ struct imx6_cpuidle_pm_info *cpuidle_pm_info;
+ int i;
+ const u32 *mmdc_offset_array;
+ u32 wfi_code_size;
+
+ wfi_iram_base_phys = (void *)(iram_tlb_phys_addr + MX6_CPUIDLE_IRAM_ADDR_OFFSET);
+
+ /* Make sure wfi_iram_base is 8 byte aligned. */
+ if ((uintptr_t)(wfi_iram_base_phys) & (FNCPY_ALIGN - 1))
+ wfi_iram_base_phys += FNCPY_ALIGN - ((uintptr_t)wfi_iram_base_phys % (FNCPY_ALIGN));
+
+ wfi_iram_base = (void *)IMX_IO_P2V((unsigned long) wfi_iram_base_phys);
+
+ cpuidle_pm_info = wfi_iram_base;
+ cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
+ cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
+ cpuidle_pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
+ cpuidle_pm_info->mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset);
+ mmdc_offset_array = imx6sx_mmdc_io_offset;
+
+ cpuidle_pm_info->mmdc_base.pbase = MX6Q_MMDC_P0_BASE_ADDR;
+ cpuidle_pm_info->mmdc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR);
+
+ cpuidle_pm_info->ccm_base.pbase = MX6Q_CCM_BASE_ADDR;
+ cpuidle_pm_info->ccm_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_CCM_BASE_ADDR);
+
+ cpuidle_pm_info->anatop_base.pbase = MX6Q_ANATOP_BASE_ADDR;
+ cpuidle_pm_info->anatop_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+
+ cpuidle_pm_info->gpc_base.pbase = MX6Q_GPC_BASE_ADDR;
+ cpuidle_pm_info->gpc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_GPC_BASE_ADDR);
+
+ cpuidle_pm_info->iomuxc_base.pbase = MX6Q_IOMUXC_BASE_ADDR;
+ cpuidle_pm_info->iomuxc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR);
+
+ cpuidle_pm_info->l2_base.pbase = MX6Q_L2_BASE_ADDR;
+ cpuidle_pm_info->l2_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_L2_BASE_ADDR);
+
+ cpuidle_pm_info->src_base.pbase = MX6Q_SRC_BASE_ADDR;
+ cpuidle_pm_info->src_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_SRC_BASE_ADDR);
+
+ cpuidle_pm_info->sema4_base.pbase = MX6Q_SEMA4_BASE_ADDR;
+ cpuidle_pm_info->sema4_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX6Q_SEMA4_BASE_ADDR);
+
+ /* only save mmdc io offset, settings will be saved in asm code */
+ for (i = 0; i < cpuidle_pm_info->mmdc_io_num; i++)
+ cpuidle_pm_info->mmdc_io_val[i][0] = mmdc_offset_array[i];
+
+ /* code size should include cpuidle_pm_info size */
+ wfi_code_size = (&mx6sx_lpm_wfi_end -&mx6sx_lpm_wfi_start) *4 + sizeof(*cpuidle_pm_info);
+ imx6sx_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base + sizeof(*cpuidle_pm_info),
+ &imx6sx_low_power_idle, wfi_code_size);
+#endif
+
imx6_set_int_mem_clk_lpm(true);
- imx6_enable_rbc(false);
- imx_gpc_set_l2_mem_power_in_lpm(false);
- /*
- * set ARM power up/down timing to the fastest,
- * sw2iso and sw can be set to one 32K cycle = 31us
- * except for power up sw2iso which need to be
- * larger than LDO ramp up time.
- */
- imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1);
- imx_gpc_set_arm_power_down_timing(1, 1);
+
+ if (imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) {
+ /*
+ * enable RC-OSC here, as it needs at least 4ms for RC-OSC to
+ * be stable, low power idle flow can NOT endure this big
+ * latency, so we make RC-OSC self-tuning enabled here.
+ */
+ val = readl_relaxed(anatop_base + PMU_LOW_PWR_CTRL);
+ val |= 0x1;
+ writel_relaxed(val, anatop_base + PMU_LOW_PWR_CTRL);
+ /*
+ * config RC-OSC freq
+ * tune_enable = 1;tune_start = 1;hyst_plus = 0;hyst_minus = 0;
+ * osc_prog = 0xa7;
+ */
+ writel_relaxed(
+ 0x4 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT |
+ 0xa7 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_START_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set count_trg = 0x2dc */
+ writel_relaxed(
+ 0x40 << XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT |
+ 0x2dc << XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG1);
+ /* wait 4ms according to hardware design */
+ msleep(4);
+ /*
+ * now add some hysteresis, hyst_plus=3, hyst_minus=3
+ * (the minimum hysteresis that looks good is 2)
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG0);
+ val &= ~((XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT));
+ val |= (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set the count_1m_trg = 0x2d7 */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG2);
+ val &= ~(XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK <<
+ XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT);
+ val |= 0x2d7 << XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT;
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG2);
+ /*
+ * hardware design require to write XTALOSC24M_OSC_CONFIG0 or
+ * XTALOSC24M_OSC_CONFIG1 to
+ * make XTALOSC24M_OSC_CONFIG2 write work
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG1);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG1);
+ }
return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
}
diff --git a/arch/arm/mach-imx/cpuidle-imx6ul.c b/arch/arm/mach-imx/cpuidle-imx6ul.c
new file mode 100644
index 000000000000..4f22b8f0d02b
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6ul.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
+ * 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/busfreq-imx.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/psci.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <asm/cpuidle.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include <uapi/linux/psci.h>
+
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+#define MAX_MMDC_IO_NUM 14
+
+#define PMU_LOW_PWR_CTRL 0x270
+#define XTALOSC24M_OSC_CONFIG0 0x2a0
+#define XTALOSC24M_OSC_CONFIG1 0x2b0
+#define XTALOSC24M_OSC_CONFIG2 0x2c0
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT 24
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT 16
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT 12
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT 4
+#define XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT 1
+#define XTALOSC24M_OSC_CONFIG0_START_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT 20
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK 0xfff
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT 0
+
+extern unsigned long iram_tlb_phys_addr;
+static void __iomem *wfi_iram_base;
+
+#ifdef CONFIG_CPU_FREQ
+static void __iomem *wfi_iram_base_phys;
+extern unsigned long mx6ul_lpm_wfi_start asm("mx6ul_lpm_wfi_start");
+extern unsigned long mx6ul_lpm_wfi_end asm("mx6ul_lpm_wfi_end");
+extern unsigned long mx6ull_lpm_wfi_start asm("mx6ull_lpm_wfi_start");
+extern unsigned long mx6ull_lpm_wfi_end asm("mx6ull_lpm_wfi_end");
+#endif
+
+struct imx6_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+struct imx6_cpuidle_pm_info {
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 pm_info_size; /* Size of pm_info. */
+ u32 ttbr;
+ struct imx6_pm_base mmdc_base;
+ struct imx6_pm_base iomuxc_base;
+ struct imx6_pm_base ccm_base;
+ struct imx6_pm_base gpc_base;
+ struct imx6_pm_base anatop_base;
+ struct imx6_pm_base src_base;
+ u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
+ u32 mmdc_io_val[MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+static const u32 imx6ul_mmdc_io_offset[] __initconst = {
+ 0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
+ 0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
+ 0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */
+ 0x494, 0x4b0, /* MODE_CTL, MODE, */
+};
+
+static void (*imx6ul_wfi_in_iram_fn)(void __iomem *iram_vbase);
+
+#define MX6UL_POWERDWN_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+static int imx6ul_idle_finish(unsigned long val)
+{
+ if (psci_ops.cpu_suspend)
+ psci_ops.cpu_suspend(MX6UL_POWERDWN_IDLE_PARAM,
+ __pa(cpu_resume));
+ else
+ imx6ul_wfi_in_iram_fn(wfi_iram_base);
+
+ return 0;
+}
+
+static int imx6ul_enter_wait(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ int mode = get_bus_freq_mode();
+
+ imx6_set_lpm(WAIT_UNCLOCKED);
+ if ((index == 1) || ((mode != BUS_FREQ_LOW) && index == 2)) {
+ cpu_do_idle();
+ index = 1;
+ } else {
+ /*
+ * i.MX6UL TO1.0 ARM power up uses IPG/2048 as clock source,
+ * from TO1.1, PGC_CPU_PUPSCR bit [5] is re-defined to switch
+ * clock to IPG/32, enable this bit to speed up the ARM power
+ * up process in low power idle case.
+ */
+ if (cpu_is_imx6ul() && imx_get_soc_revision() >
+ IMX_CHIP_REVISION_1_0)
+ imx_gpc_switch_pupscr_clk(true);
+ /* Need to notify there is a cpu pm operation. */
+ cpu_pm_enter();
+ cpu_cluster_pm_enter();
+
+ cpu_suspend(0, imx6ul_idle_finish);
+
+ cpu_cluster_pm_exit();
+ cpu_pm_exit();
+ imx6_enable_rbc(false);
+
+ if (cpu_is_imx6ul() && imx_get_soc_revision() >
+ IMX_CHIP_REVISION_1_0)
+ imx_gpc_switch_pupscr_clk(false);
+ }
+
+ imx6_set_lpm(WAIT_CLOCKED);
+
+ return index;
+}
+
+static struct cpuidle_driver imx6ul_cpuidle_driver_v2 = {
+ .name = "imx6ul_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .enter = imx6ul_enter_wait,
+ .name = "WAIT",
+ .desc = "Clock off",
+ },
+ /* LOW POWER IDLE */
+ {
+ /*
+ * RBC 130us + ARM gating 43us + RBC clear 65us
+ * + PLL2 relock 450us and some margin, here set
+ * it to 700us.
+ */
+ .exit_latency = 700,
+ .target_residency = 1000,
+ .enter = imx6ul_enter_wait,
+ .name = "LOW-POWER-IDLE",
+ .desc = "ARM power off",
+ }
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+static struct cpuidle_driver imx6ul_cpuidle_driver = {
+ .name = "imx6ul_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .enter = imx6ul_enter_wait,
+ .name = "WAIT",
+ .desc = "Clock off",
+ },
+ /* LOW POWER IDLE */
+ {
+ /*
+ * RBC 130us + ARM gating 1370us + RBC clear 65us
+ * + PLL2 relock 450us and some margin, here set
+ * it to 2100us.
+ */
+ .exit_latency = 2100,
+ .target_residency = 2500,
+ .enter = imx6ul_enter_wait,
+ .name = "LOW-POWER-IDLE",
+ .desc = "ARM power off",
+ }
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int __init imx6ul_cpuidle_init(void)
+{
+ void __iomem *anatop_base = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+ u32 val;
+#ifdef CONFIG_CPU_FREQ
+ struct imx6_cpuidle_pm_info *cpuidle_pm_info;
+ int i;
+ const u32 *mmdc_offset_array;
+ u32 wfi_code_size;
+
+ wfi_iram_base_phys = (void *)(iram_tlb_phys_addr + MX6_CPUIDLE_IRAM_ADDR_OFFSET);
+
+ /* Make sure wfi_iram_base is 8 byte aligned. */
+ if ((uintptr_t)(wfi_iram_base_phys) & (FNCPY_ALIGN - 1))
+ wfi_iram_base_phys += FNCPY_ALIGN - ((uintptr_t)wfi_iram_base_phys % (FNCPY_ALIGN));
+
+ wfi_iram_base = (void *)IMX_IO_P2V((unsigned long) wfi_iram_base_phys);
+
+ cpuidle_pm_info = wfi_iram_base;
+ cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
+ cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
+ cpuidle_pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
+ cpuidle_pm_info->mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset);
+ mmdc_offset_array = imx6ul_mmdc_io_offset;
+
+ cpuidle_pm_info->mmdc_base.pbase = MX6Q_MMDC_P0_BASE_ADDR;
+ cpuidle_pm_info->mmdc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR);
+
+ cpuidle_pm_info->ccm_base.pbase = MX6Q_CCM_BASE_ADDR;
+ cpuidle_pm_info->ccm_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_CCM_BASE_ADDR);
+
+ cpuidle_pm_info->anatop_base.pbase = MX6Q_ANATOP_BASE_ADDR;
+ cpuidle_pm_info->anatop_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
+
+ cpuidle_pm_info->gpc_base.pbase = MX6Q_GPC_BASE_ADDR;
+ cpuidle_pm_info->gpc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_GPC_BASE_ADDR);
+
+ cpuidle_pm_info->iomuxc_base.pbase = MX6Q_IOMUXC_BASE_ADDR;
+ cpuidle_pm_info->iomuxc_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR);
+
+ cpuidle_pm_info->src_base.pbase = MX6Q_SRC_BASE_ADDR;
+ cpuidle_pm_info->src_base.vbase = (void __iomem *)IMX_IO_P2V(MX6Q_SRC_BASE_ADDR);
+
+ /* Only save mmdc io offset, settings will be saved in asm code */
+ for (i = 0; i < cpuidle_pm_info->mmdc_io_num; i++)
+ cpuidle_pm_info->mmdc_io_val[i][0] = mmdc_offset_array[i];
+
+ /* calculate the wfi code size */
+ if (cpu_is_imx6ul()) {
+ wfi_code_size = (&mx6ul_lpm_wfi_end -&mx6ul_lpm_wfi_start) *4;
+
+ imx6ul_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base + sizeof(*cpuidle_pm_info),
+ &imx6ul_low_power_idle, wfi_code_size);
+ } else {
+ wfi_code_size = (&mx6ull_lpm_wfi_end -&mx6ull_lpm_wfi_start) *4;
+
+ imx6ul_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base + sizeof(*cpuidle_pm_info),
+ &imx6ull_low_power_idle, wfi_code_size);
+ }
+#endif
+
+ imx6_set_int_mem_clk_lpm(true);
+
+ /*
+ * enable RC-OSC here, as it needs at least 4ms for RC-OSC to
+ * be stable, low power idle flow can NOT endure this big
+ * latency, so we make RC-OSC self-tuning enabled here.
+ */
+ val = readl_relaxed(anatop_base + PMU_LOW_PWR_CTRL);
+ val |= 0x1;
+ writel_relaxed(val, anatop_base + PMU_LOW_PWR_CTRL);
+ /*
+ * config RC-OSC freq
+ * tune_enable = 1;tune_start = 1;hyst_plus = 0;hyst_minus = 0;
+ * osc_prog = 0xa7;
+ */
+ writel_relaxed(
+ 0x4 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT |
+ 0xa7 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_START_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set count_trg = 0x2dc */
+ writel_relaxed(
+ 0x40 << XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT |
+ 0x2dc << XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG1);
+ /* wait 4ms according to hardware design */
+ msleep(4);
+ /*
+ * now add some hysteresis, hyst_plus=3, hyst_minus=3
+ * (the minimum hysteresis that looks good is 2)
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG0);
+ val &= ~((XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT));
+ val |= (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set the count_1m_trg = 0x2d7 */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG2);
+ val &= ~(XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK <<
+ XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT);
+ val |= 0x2d7 << XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT;
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG2);
+ /*
+ * hardware design require to write XTALOSC24M_OSC_CONFIG0 or
+ * XTALOSC24M_OSC_CONFIG1 to
+ * make XTALOSC24M_OSC_CONFIG2 write work
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG1);
+
+ /* ARM power up time is reduced since TO1.1 */
+ if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_0)
+ return cpuidle_register(&imx6ul_cpuidle_driver_v2, NULL);
+ else
+ return cpuidle_register(&imx6ul_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle-imx7d.c b/arch/arm/mach-imx/cpuidle-imx7d.c
new file mode 100644
index 000000000000..8e1e61c5503b
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx7d.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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/busfreq-imx.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/psci.h>
+#include <asm/cp15.h>
+#include <asm/cpuidle.h>
+#include <asm/fncpy.h>
+#include <asm/mach/map.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include <uapi/linux/psci.h>
+
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+#define XTALOSC24M_OSC_CONFIG0 0x10
+#define XTALOSC24M_OSC_CONFIG1 0x20
+#define XTALOSC24M_OSC_CONFIG2 0x30
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT 24
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT 16
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK 0xf
+#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT 12
+#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT 4
+#define XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT 1
+#define XTALOSC24M_OSC_CONFIG0_START_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT 20
+#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT 0
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK 0xfff
+#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT 0
+
+#define XTALOSC_CTRL_24M 0x0
+#define XTALOSC_CTRL_24M_RC_OSC_EN_SHIFT 13
+#define REG_SET 0x4
+
+static void __iomem *wfi_iram_base;
+static void __iomem *wfi_iram_base_phys;
+extern unsigned long iram_tlb_phys_addr;
+
+struct imx7_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+struct imx7_cpuidle_pm_info {
+ phys_addr_t vbase; /* The virtual address of pm_info. */
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 pm_info_size;
+ u32 ttbr;
+ u32 num_online_cpus;
+ u32 num_lpi_cpus;
+ atomic_t val;
+ atomic_t flag0;
+ atomic_t flag1;
+ struct imx7_pm_base ddrc_base;
+ struct imx7_pm_base ccm_base;
+ struct imx7_pm_base anatop_base;
+ struct imx7_pm_base src_base;
+ struct imx7_pm_base iomuxc_gpr_base;
+ struct imx7_pm_base gpc_base;
+ struct imx7_pm_base gic_dist_base;
+} __aligned(8);
+
+static atomic_t master_lpi = ATOMIC_INIT(0);
+static atomic_t master_wait = ATOMIC_INIT(0);
+
+static void (*imx7d_wfi_in_iram_fn)(void __iomem *iram_vbase);
+static struct imx7_cpuidle_pm_info *cpuidle_pm_info;
+
+#define MX7D_POWERDWN_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+#define MX7D_STANDBY_IDLE_PARAM \
+ ((1 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_STANDBY << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+/* Mapped for the kernel, unlike cpuidle_pm_info->gic_dist_base.vbase */
+static void __iomem *imx7d_cpuidle_gic_base;
+
+static void imx_pen_lock(int cpu)
+{
+ if (cpu == 0) {
+ atomic_set(&cpuidle_pm_info->flag0, 1);
+ dsb();
+ atomic_set(&cpuidle_pm_info->val, cpu);
+ do {
+ dsb();
+ } while (atomic_read(&cpuidle_pm_info->flag1) == 1
+ && atomic_read(&cpuidle_pm_info->val) == cpu)
+ ;
+ } else {
+ atomic_set(&cpuidle_pm_info->flag1, 1);
+ dsb();
+ atomic_set(&cpuidle_pm_info->val, cpu);
+ do {
+ dsb();
+ } while (atomic_read(&cpuidle_pm_info->flag0) == 1
+ && atomic_read(&cpuidle_pm_info->val) == cpu)
+ ;
+ }
+}
+
+static void imx_pen_unlock(int cpu)
+{
+ dsb();
+ if (cpu == 0)
+ atomic_set(&cpuidle_pm_info->flag0, 0);
+ else
+ atomic_set(&cpuidle_pm_info->flag1, 0);
+}
+
+static int imx7d_idle_finish(unsigned long val)
+{
+ if (psci_ops.cpu_suspend)
+ psci_ops.cpu_suspend(MX7D_POWERDWN_IDLE_PARAM, __pa(cpu_resume));
+ else
+ imx7d_wfi_in_iram_fn(wfi_iram_base);
+
+ return 0;
+}
+
+static bool imx7d_gic_sgis_pending(void)
+{
+ void __iomem *sgip_base = imx7d_cpuidle_gic_base + 0x1f20;
+
+ return (readl_relaxed(sgip_base + 0x0) |
+ readl_relaxed(sgip_base + 0x4) |
+ readl_relaxed(sgip_base + 0x8) |
+ readl_relaxed(sgip_base + 0xc));
+}
+
+static DEFINE_SPINLOCK(psci_lock);
+static int imx7d_enter_low_power_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ int mode = get_bus_freq_mode();
+
+
+ if ((index == 1) || ((mode != BUS_FREQ_LOW) && index == 2)) {
+ index = 1;
+ if (atomic_inc_return(&master_wait) == num_online_cpus())
+ imx_gpcv2_set_lpm_mode(WAIT_UNCLOCKED);
+
+ cpu_do_idle();
+
+ atomic_dec(&master_wait);
+ imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
+ } else {
+ if (psci_ops.cpu_suspend) {
+ cpu_pm_enter();
+ spin_lock(&psci_lock);
+ if (atomic_inc_return(&master_lpi) == num_online_cpus()) {
+ if (imx7d_gic_sgis_pending()) {
+ atomic_dec(&master_lpi);
+ index = -1;
+ goto psci_skip_lpi_flow;
+ }
+
+ imx_gpcv2_set_lpm_mode(WAIT_UNCLOCKED);
+ imx_gpcv2_set_cpu_power_gate_in_idle(true);
+
+ cpu_cluster_pm_enter();
+ }
+ spin_unlock(&psci_lock);
+
+ cpu_suspend(0, imx7d_idle_finish);
+
+ spin_lock(&psci_lock);
+ if (atomic_read(&master_lpi) == num_online_cpus()) {
+ cpu_cluster_pm_exit();
+ imx_gpcv2_set_cpu_power_gate_in_idle(false);
+ imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
+ }
+
+ atomic_dec(&master_lpi);
+psci_skip_lpi_flow:
+ spin_unlock(&psci_lock);
+ cpu_pm_exit();
+ } else {
+ imx_pen_lock(dev->cpu);
+ cpuidle_pm_info->num_online_cpus = num_online_cpus();
+ ++cpuidle_pm_info->num_lpi_cpus;
+ cpu_pm_enter();
+ if (cpuidle_pm_info->num_lpi_cpus ==
+ cpuidle_pm_info->num_online_cpus) {
+ /*
+ * GPC will not wake on SGIs so check for them
+ * manually here. At this point we know the other cpu
+ * is in wfi or waiting for the lock and can't send
+ * any additional IPIs.
+ */
+ if (imx7d_gic_sgis_pending()) {
+ index = -1;
+ goto skip_lpi_flow;
+ }
+ imx_gpcv2_set_lpm_mode(WAIT_UNCLOCKED);
+ imx_gpcv2_set_cpu_power_gate_in_idle(true);
+ cpu_cluster_pm_enter();
+ } else {
+ imx_set_cpu_jump(dev->cpu, ca7_cpu_resume);
+ }
+
+ cpu_suspend(0, imx7d_idle_finish);
+
+ if (cpuidle_pm_info->num_lpi_cpus ==
+ cpuidle_pm_info->num_online_cpus) {
+ cpu_cluster_pm_exit();
+ imx_gpcv2_set_cpu_power_gate_in_idle(false);
+ imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
+ }
+
+skip_lpi_flow:
+ cpu_pm_exit();
+ --cpuidle_pm_info->num_lpi_cpus;
+ imx_pen_unlock(dev->cpu);
+ }
+ }
+
+ return index;
+}
+
+static struct cpuidle_driver imx7d_cpuidle_driver = {
+ .name = "imx7d_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT MODE */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .enter = imx7d_enter_low_power_idle,
+ .name = "WAIT",
+ .desc = "Clock off",
+ },
+ /* LOW POWER IDLE */
+ {
+ .exit_latency = 10000,
+ .target_residency = 20000,
+ .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .enter = imx7d_enter_low_power_idle,
+ .name = "LOW-POWER-IDLE",
+ .desc = "ARM power off",
+ },
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int imx7d_enable_rcosc(void)
+{
+ void __iomem *anatop_base =
+ (void __iomem *)IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR);
+ u32 val;
+
+ imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
+ /* set RC-OSC freq and turn it on */
+ writel_relaxed(0x1 << XTALOSC_CTRL_24M_RC_OSC_EN_SHIFT,
+ anatop_base + XTALOSC_CTRL_24M + REG_SET);
+ /*
+ * config RC-OSC freq
+ * tune_enable = 1;tune_start = 1;hyst_plus = 0;hyst_minus = 0;
+ * osc_prog = 0xa7;
+ */
+ writel_relaxed(
+ 0x4 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT |
+ 0xa7 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT |
+ 0x1 << XTALOSC24M_OSC_CONFIG0_START_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set count_trg = 0x2dc */
+ writel_relaxed(
+ 0x40 << XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT |
+ 0x2dc << XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT,
+ anatop_base + XTALOSC24M_OSC_CONFIG1);
+ /* wait at least 4ms according to hardware design */
+ mdelay(6);
+ /*
+ * now add some hysteresis, hyst_plus=3, hyst_minus=3
+ * (the minimum hysteresis that looks good is 2)
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG0);
+ val &= ~((XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK <<
+ XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT));
+ val |= (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) |
+ (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG0);
+ /* set the count_1m_trg = 0x2d7 */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG2);
+ val &= ~(XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK <<
+ XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT);
+ val |= 0x2d7 << XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT;
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG2);
+ /*
+ * hardware design require to write XTALOSC24M_OSC_CONFIG0 or
+ * XTALOSC24M_OSC_CONFIG1 to
+ * make XTALOSC24M_OSC_CONFIG2 write work
+ */
+ val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG1);
+ writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG1);
+
+ return 0;
+}
+
+int __init imx7d_cpuidle_init(void)
+{
+ wfi_iram_base_phys = (void *)(iram_tlb_phys_addr +
+ MX7_CPUIDLE_OCRAM_ADDR_OFFSET);
+
+ /* Make sure wfi_iram_base is 8 byte aligned. */
+ if ((uintptr_t)(wfi_iram_base_phys) & (FNCPY_ALIGN - 1))
+ wfi_iram_base_phys += FNCPY_ALIGN -
+ ((uintptr_t)wfi_iram_base_phys % (FNCPY_ALIGN));
+
+ wfi_iram_base = (void *)IMX_IO_P2V((unsigned long) wfi_iram_base_phys);
+
+ cpuidle_pm_info = wfi_iram_base;
+ cpuidle_pm_info->vbase = (phys_addr_t) wfi_iram_base;
+ cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
+ cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
+ cpuidle_pm_info->resume_addr = virt_to_phys(ca7_cpu_resume);
+ cpuidle_pm_info->num_online_cpus = num_online_cpus();
+
+ cpuidle_pm_info->ddrc_base.pbase = MX7D_DDRC_BASE_ADDR;
+ cpuidle_pm_info->ddrc_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_DDRC_BASE_ADDR);
+
+ cpuidle_pm_info->ccm_base.pbase = MX7D_CCM_BASE_ADDR;
+ cpuidle_pm_info->ccm_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_CCM_BASE_ADDR);
+
+ cpuidle_pm_info->anatop_base.pbase = MX7D_ANATOP_BASE_ADDR;
+ cpuidle_pm_info->anatop_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR);
+
+ cpuidle_pm_info->src_base.pbase = MX7D_SRC_BASE_ADDR;
+ cpuidle_pm_info->src_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_SRC_BASE_ADDR);
+
+ cpuidle_pm_info->iomuxc_gpr_base.pbase = MX7D_IOMUXC_GPR_BASE_ADDR;
+ cpuidle_pm_info->iomuxc_gpr_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR);
+
+ cpuidle_pm_info->gpc_base.pbase = MX7D_GPC_BASE_ADDR;
+ cpuidle_pm_info->gpc_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_GPC_BASE_ADDR);
+
+ cpuidle_pm_info->gic_dist_base.pbase = MX7D_GIC_BASE_ADDR;
+ cpuidle_pm_info->gic_dist_base.vbase =
+ (void __iomem *)IMX_IO_P2V(MX7D_GIC_BASE_ADDR);
+
+ imx7d_cpuidle_gic_base = ioremap(MX7D_GIC_BASE_ADDR, MX7D_GIC_SIZE);
+
+ imx7d_enable_rcosc();
+
+ /* code size should include cpuidle_pm_info size */
+ if (!psci_ops.cpu_suspend) {
+ imx7d_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base +
+ sizeof(*cpuidle_pm_info),
+ &imx7d_low_power_idle,
+ MX7_CPUIDLE_OCRAM_SIZE - sizeof(*cpuidle_pm_info));
+ }
+
+ return cpuidle_register(&imx7d_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index ce552c096cae..340b0e3af05f 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -8,7 +8,11 @@
extern int imx5_cpuidle_init(void);
extern int imx6q_cpuidle_init(void);
extern int imx6sl_cpuidle_init(void);
+extern int imx6sll_cpuidle_init(void);
extern int imx6sx_cpuidle_init(void);
+extern int imx6ul_cpuidle_init(void);
+extern int imx7d_cpuidle_init(void);
+extern int imx7d_enable_rcosc(void);
extern int imx7ulp_cpuidle_init(void);
#else
static inline int imx5_cpuidle_init(void)
@@ -23,10 +27,26 @@ static inline int imx6sl_cpuidle_init(void)
{
return 0;
}
+static inline int imx6sll_cpuidle_init(void)
+{
+ return 0;
+}
static inline int imx6sx_cpuidle_init(void)
{
return 0;
}
+static inline int imx6ul_cpuidle_init(void)
+{
+ return 0;
+}
+static inline int imx7d_cpuidle_init(void)
+{
+ return 0;
+}
+static inline int imx7d_enable_rcosc(void)
+{
+ return 0;
+}
static inline int imx7ulp_cpuidle_init(void)
{
return 0;
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6.S b/arch/arm/mach-imx/ddr3_freq_imx6.S
new file mode 100644
index 000000000000..e6f7f74f7d32
--- /dev/null
+++ b/arch/arm/mach-imx/ddr3_freq_imx6.S
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include <asm/smp_scu.h>
+#include "hardware.h"
+
+#define MMDC0_MDPDC 0x4
+#define MMDC0_MDCF0 0x0c
+#define MMDC0_MDCF1 0x10
+#define MMDC0_MDMISC 0x18
+#define MMDC0_MDSCR 0x1c
+#define MMDC0_MAARCR 0x400
+#define MMDC0_MAPSR 0x404
+#define MMDC0_MADPCR0 0x410
+#define MMDC0_MPZQHWCTRL 0x800
+#define MMDC1_MPZQHWCTRL 0x4800
+#define MMDC0_MPODTCTRL 0x818
+#define MMDC1_MPODTCTRL 0x4818
+#define MMDC0_MPDGCTRL0 0x83c
+#define MMDC1_MPDGCTRL0 0x483c
+#define MMDC0_MPMUR0 0x8b8
+#define MMDC1_MPMUR0 0x48b8
+
+#define CCM_CBCDR 0x14
+#define CCM_CBCMR 0x18
+#define CCM_CSCMR1 0x1c
+#define CCM_CDHIPR 0x48
+
+#define L2_CACHE_SYNC 0x730
+#define PL310_AUX_CTRL 0x104
+#define PL310_DCACHE_LOCKDOWN_BASE 0x900
+#define PL310_AUX_16WAY_BIT 0x10000
+#define PL310_LOCKDOWN_NBREGS 8
+#define PL310_LOCKDOWN_SZREG 4
+#define PL310_8WAYS_MASK 0x00FF
+#define PL310_16WAYS_UPPERMASK 0xFF00
+
+#define IMX6QP_REVISION_ID 0x630100
+#define ANADIG_DIGPROG 0x260
+
+.extern iram_tlb_phys_addr
+
+.globl mx6_ddr3_freq_change_start
+.globl mx6_ddr3_freq_change_end
+
+ .align 3
+
+ .macro is_mx6qp
+
+ /* check if the SOC is i.MX6QP */
+ ldr r0, =IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR)
+ ldr r1, [r0, #ANADIG_DIGPROG]
+ ldr r2, =IMX6QP_REVISION_ID
+ cmp r1, r2
+
+ .endm
+
+ .macro switch_to_528MHz
+
+ /* check if periph_clk_sel is already set */
+ ldr r0, [r6, #CCM_CBCDR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ beq set_ahb_podf_before_switch
+
+ /* change periph_clk to be sourced from pll3_clk. */
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(3 << 12)
+ str r0, [r6, #CCM_CBCMR]
+
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(0x38 << 20)
+ str r0, [r6, #CCM_CBCDR]
+
+ /*
+ * set the AHB dividers before the switch,
+ * don't change AXI clock divider,
+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
+ */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0xd00
+ orr r0, r0, #(1 << 16)
+ str r0, [r6, #CCM_CBCDR]
+
+wait_div_update528:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update528
+
+ /* now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #CCM_CBCDR]
+ orr r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch3:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch3
+
+ b switch_pre_periph_clk_528
+
+set_ahb_podf_before_switch:
+ /*
+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
+ */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #0xd00
+ orr r0, r0, #(1 << 16)
+ str r0, [r6, #CCM_CBCDR]
+
+wait_div_update528_1:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update528_1
+
+switch_pre_periph_clk_528:
+
+ /* now switch pre_periph_clk to PLL2_528MHz. */
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(0xc << 16)
+ str r0, [r6, #CCM_CBCMR]
+
+ /* now switch periph_clk back. */
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch4:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch4
+
+ .endm
+
+ .macro switch_to_400MHz
+
+ /* check if periph_clk_sel is already set. */
+ ldr r0, [r6, #CCM_CBCDR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ beq set_ahb_podf_before_switch1
+
+ /* change periph_clk to be sourced from pll3_clk. */
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(3 << 12)
+ str r0, [r6, #CCM_CBCMR]
+
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(0x38 << 24)
+ str r0, [r6, #CCM_CBCDR]
+
+ /* now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #CCM_CBCDR]
+ orr r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch5:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch5
+
+ b switch_pre_periph_clk_400
+
+set_ahb_podf_before_switch1:
+ /*
+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
+ */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #(0x9 << 8)
+ orr r0, r0, #(1 << 16)
+ str r0, [r6, #CCM_CBCDR]
+
+wait_div_update400_1:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update400_1
+
+switch_pre_periph_clk_400:
+
+ /* now switch pre_periph_clk to PFD_400MHz. */
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(0xc << 16)
+ orr r0, r0, #(0x4 << 16)
+ str r0, [r6, #CCM_CBCMR]
+
+ /* now switch periph_clk back. */
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch6:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch6
+
+ /*
+ * change AHB divider so that we are at 400/3=133MHz.
+ * don't change AXI clock divider.
+ * set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3,
+ */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #(0x9 << 8)
+ orr r0, r0, #(1 << 16)
+ str r0, [r6, #CCM_CBCDR]
+
+wait_div_update400_2:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update400_2
+
+ .endm
+
+ .macro switch_to_50MHz
+
+ /* check if periph_clk_sel is already set. */
+ ldr r0, [r6, #CCM_CBCDR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ beq switch_pre_periph_clk_50
+
+ /*
+ * set the periph_clk to be sourced from PLL2_PFD_200M
+ * change periph_clk to be sourced from pll3_clk.
+ * ensure PLL3 is the source and set the divider to 1.
+ */
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(0x3 << 12)
+ str r0, [r6, #CCM_CBCMR]
+
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(0x38 << 24)
+ str r0, [r6, #CCM_CBCDR]
+
+ /* now switch periph_clk to pll3_main_clk. */
+ ldr r0, [r6, #CCM_CBCDR]
+ orr r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch_50:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch_50
+
+switch_pre_periph_clk_50:
+
+ /* now switch pre_periph_clk to PFD_200MHz. */
+ ldr r0, [r6, #CCM_CBCMR]
+ orr r0, r0, #(0xc << 16)
+ str r0, [r6, #CCM_CBCMR]
+
+ /*
+ * set the MMDC_DIV=4, AXI_DIV = 4, AHB_DIV=8,
+ */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #(0x18 << 16)
+ orr r0, r0, #(0x3 << 16)
+
+ /*
+ * if changing AHB divider remember to change
+ * the IPGPER divider too below.
+ */
+ orr r0, r0, #0x1d00
+ str r0, [r6, #CCM_CBCDR]
+
+wait_div_update_50:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update_50
+
+ /* now switch periph_clk back. */
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch2:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch2
+
+ .endm
+
+ .macro switch_to_24MHz
+ /*
+ * change the freq now try setting DDR to 24MHz.
+ * source it from the periph_clk2 ensure the
+ * periph_clk2 is sourced from 24MHz and the
+ * divider is 1.
+ */
+
+ ldr r0, [r6, #CCM_CBCMR]
+ bic r0, r0, #(0x3 << 12)
+ orr r0, r0, #(1 << 12)
+ str r0, [r6, #CCM_CBCMR]
+
+ ldr r0, [r6, #CCM_CBCDR]
+ bic r0, r0, #(0x38 << 24)
+ str r0, [r6, #CCM_CBCDR]
+
+ /* now switch periph_clk to 24MHz. */
+ ldr r0, [r6, #CCM_CBCDR]
+ orr r0, r0, #(1 << 25)
+ str r0, [r6, #CCM_CBCDR]
+
+periph_clk_switch1:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne periph_clk_switch1
+
+ /* change all the dividers to 1. */
+ ldr r0, [r6, #CCM_CBCDR]
+ ldr r2, =0x3f1f00
+ bic r0, r0, r2
+ orr r0, r0, #(1 << 8)
+ str r0, [r6, #CCM_CBCDR]
+
+ /* Wait for the divider to change. */
+wait_div_update:
+ ldr r0, [r6, #CCM_CDHIPR]
+ cmp r0, #0
+ bne wait_div_update
+
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ .endm
+
+/*
+ * mx6_ddr3_freq_change
+ *
+ * idle the processor (eg, wait for interrupt).
+ * make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(mx6_ddr3_freq_change)
+
+mx6_ddr3_freq_change_start:
+ stmfd sp!, {r4-r12}
+
+ /*
+ * r5 -> mmdc_base
+ * r6 -> ccm_base
+ * r7 -> iomux_base
+ * r12 -> l2_base
+ */
+ mov r4, r0
+ mov r8, r1
+ mov r9, r2
+ mov r11, r3
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /*
+ * Need to flush and disable L1 before
+ * disabling L2, we need data to
+ * coherent. Flushing L1 pushes
+ * everyhting to L2. We sync L2 later, but
+ * it can still have dirty lines.
+ * While exiting, we need to enable L2 first
+ * and then L1.
+ */
+ disable_l1_dcache
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Make sure the L2 buffers are drained.
+ * Sync operation on L2 drains the buffers.
+ */
+ ldr r12, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r1, [r12, #L2_CACHE_SYNC]
+ cmp r1, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r1, #0x0
+ str r1, [r12, #L2_CACHE_SYNC]
+
+ dsb
+ isb
+
+ ldr r1, [r12, #PL310_AUX_CTRL]
+ tst r1, #PL310_AUX_16WAY_BIT
+ mov r1, #PL310_8WAYS_MASK
+ orrne r1, #PL310_16WAYS_UPPERMASK
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ add r5, r12, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r1, [r5], #PL310_LOCKDOWN_SZREG
+ str r1, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+
+ /* Now switch the TTBR. */
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+
+ ldr r5, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+ ldr r6, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r7, =IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR)
+
+ /* Read the Original MU delay value */
+ ldr r1, [r5, #MMDC0_MPMUR0]
+ mov r10, r1, lsr #16
+ ldr r1, =0x3ff
+ and r10, r10, r1
+
+ /* disable automatic power saving. */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ orr r0, r0, #0x01
+ str r0, [r5, #MMDC0_MAPSR]
+
+ /* disable MMDC power down timer. */
+ ldr r0, [r5, #MMDC0_MDPDC]
+ bic r0, r0, #(0xff << 8)
+ str r0, [r5, #MMDC0_MDPDC]
+
+ /* delay for a while */
+ ldr r1, =4
+delay1:
+ ldr r2, =0
+cont1:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont1
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay1
+
+ /* set CON_REG */
+ ldr r0, =0x8000
+ str r0, [r5, #MMDC0_MDSCR]
+poll_conreq_set_1:
+ ldr r0, [r5, #MMDC0_MDSCR]
+ and r0, r0, #(0x4 << 12)
+ cmp r0, #(0x4 << 12)
+ bne poll_conreq_set_1
+
+ /*
+ * if requested frequency is great than
+ * 300MHz, skip setting bypass adopt mode.
+ */
+ ldr r1, =300000000
+ cmp r4, r1
+ bge 1f
+
+ is_mx6qp
+ bne 1f
+ /* Switch to adopt mode, set MMDC0_MAARCR bit25~26 to 2b'01 */
+ ldr r0, [r5, #MMDC0_MAARCR]
+ bic r0, r0, #(0x3 << 25)
+ orr r0, #(0x01 << 25)
+ str r0 , [r5, #MMDC0_MAARCR]
+1:
+ ldr r0, =0x00008050
+ str r0, [r5, #MMDC0_MDSCR]
+ ldr r0, =0x00008058
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /*
+ * if requested frequency is greater than
+ * 300MHz go to DLL on mode.
+ */
+ ldr r1, =300000000
+ cmp r4, r1
+ bge dll_on_mode
+
+dll_off_mode:
+
+ /* if DLL is currently on, turn it off. */
+ cmp r9, #1
+ beq continue_dll_off_1
+
+ ldr r0, =0x00018031
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x00018039
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r1, =10
+delay1a:
+ ldr r2, =0
+cont1a:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont1a
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay1a
+
+continue_dll_off_1:
+ /* set DVFS - enter self refresh mode */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ orr r0, r0, #(1 << 21)
+ str r0, [r5, #MMDC0_MAPSR]
+
+ /* de-assert con_req */
+ mov r0, #0x0
+ str r0, [r5, #MMDC0_MDSCR]
+
+poll_dvfs_set_1:
+ ldr r0, [r5, #MMDC0_MAPSR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ bne poll_dvfs_set_1
+
+ ldr r1, =24000000
+ cmp r4, r1
+ beq switch_freq_24
+
+ switch_to_50MHz
+ b continue_dll_off_2
+
+switch_freq_24:
+ switch_to_24MHz
+
+continue_dll_off_2:
+
+ /* set SBS - block ddr accesses */
+ ldr r0, [r5, #MMDC0_MADPCR0]
+ orr r0, r0, #(1 << 8)
+ str r0, [r5, #MMDC0_MADPCR0]
+
+ /* clear DVFS - exit from self refresh mode */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ bic r0, r0, #(1 << 21)
+ str r0, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_clear_1:
+ ldr r0, [r5, #MMDC0_MAPSR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ beq poll_dvfs_clear_1
+
+ /* if DLL was previously on, continue DLL off routine. */
+ cmp r9, #1
+ beq continue_dll_off_3
+
+ ldr r0, =0x00018031
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x00018039
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x08208030
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x08208038
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x00088032
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x0008803A
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /* delay for a while. */
+ ldr r1, =4
+delay_1:
+ ldr r2, =0
+cont_1:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont_1
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay_1
+
+ ldr r0, [r5, #MMDC0_MDCF0]
+ bic r0, r0, #0xf
+ orr r0, r0, #0x3
+ str r0, [r5, #MMDC0_MDCF0]
+
+ ldr r0, [r5, #MMDC0_MDCF1]
+ bic r0, r0, #0x7
+ orr r0, r0, #0x4
+ str r0, [r5, #MMDC0_MDCF1]
+
+ ldr r0, [r5, #MMDC0_MDMISC]
+ bic r0, r0, #(0x3 << 16) /* walat = 0x1 */
+ orr r0, r0, #(0x1 << 16)
+ bic r0, r0, #(0x7 << 6) /* ralat = 0x2 */
+ orr r0, r0, #(0x2 << 6)
+ str r0, [r5, #MMDC0_MDMISC]
+
+ /* enable dqs pull down in the IOMUX. */
+ ldr r1, [r11]
+ add r11, r11, #8
+ ldr r2, =0x3028
+update_iomux:
+ ldr r0, [r11, #0x0]
+ ldr r3, [r7, r0]
+ bic r3, r3, r2
+ orr r3, r3, #(0x3 << 12)
+ orr r3, r3, #0x28
+ str r3, [r7, r0]
+ add r11, r11, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_iomux
+
+ /* ODT disabled. */
+ ldr r0, =0x0
+ ldr r2, =MMDC0_MPODTCTRL
+ str r0, [r5, r2]
+ ldr r2, =MMDC1_MPODTCTRL
+ str r0, [r5, r2]
+
+ /* DQS gating disabled. */
+ ldr r2, =MMDC0_MPDGCTRL0
+ ldr r0, [r5, r2]
+ orr r0, r0, #(1 << 29)
+ str r0, [r5, r2]
+
+ ldr r2, =MMDC1_MPDGCTRL0
+ ldr r0, [r5, r2]
+ orr r0, r0, #(0x1 << 29)
+ str r0, [r5, r2]
+
+ /* Add workaround for ERR005778.*/
+ /* double the original MU_UNIT_DEL_NUM. */
+ lsl r10, r10, #1
+
+ /* Bypass the automatic MU by setting the mu_byp_en */
+ ldr r2, [r5, #MMDC0_MPMUR0]
+ orr r2, r2, #0x400
+ orr r2, r2, r10
+ str r2, [r5, #MMDC0_MPMUR0]
+ ldr r0, =MMDC1_MPMUR0
+ str r2, [r5, r0]
+
+ /* Now perform a force measure */
+ ldr r0, [r5, #MMDC0_MPMUR0]
+ orr r0, r0, #0x800
+ str r0, [r5, #MMDC0_MPMUR0]
+ ldr r2, =MMDC1_MPMUR0
+ str r0, [r5, r2]
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r0, [r5, #MMDC0_MPMUR0]
+ and r0, r0, #0x800
+ ldr r1, [r5, r2]
+ and r1, r1, #0x800
+ orr r0, r0, r1
+ cmp r0, #0x0
+ bne 1b
+
+continue_dll_off_3:
+ /* clear SBS - unblock accesses to DDR. */
+ ldr r0, [r5, #MMDC0_MADPCR0]
+ bic r0, r0, #(0x1 << 8)
+ str r0, [r5, #MMDC0_MADPCR0]
+
+ mov r0, #0x0
+ str r0, [r5, #MMDC0_MDSCR]
+poll_conreq_clear_1:
+ ldr r0, [r5, #MMDC0_MDSCR]
+ and r0, r0, #(0x4 << 12)
+ cmp r0, #(0x4 << 12)
+ beq poll_conreq_clear_1
+
+ b done
+
+dll_on_mode:
+ /* assert DVFS - enter self refresh mode. */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ orr r0, r0, #(1 << 21)
+ str r0, [r5, #MMDC0_MAPSR]
+
+ /* de-assert CON_REQ. */
+ mov r0, #0x0
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /* poll DVFS ack. */
+poll_dvfs_set_2:
+ ldr r0, [r5, #MMDC0_MAPSR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ bne poll_dvfs_set_2
+
+ ldr r1, =528000000
+ cmp r4, r1
+ beq switch_freq_528
+
+ switch_to_400MHz
+
+ b continue_dll_on
+
+switch_freq_528:
+ switch_to_528MHz
+
+continue_dll_on:
+
+ /* set SBS step-by-step mode. */
+ ldr r0, [r5, #MMDC0_MADPCR0]
+ orr r0, r0, #( 1 << 8)
+ str r0, [r5, #MMDC0_MADPCR0]
+
+ /* clear DVFS - exit self refresh mode. */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ bic r0, r0, #(1 << 21)
+ str r0, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_clear_2:
+ ldr r0, [r5, #MMDC0_MAPSR]
+ and r0, r0, #(1 << 25)
+ cmp r0, #(1 << 25)
+ beq poll_dvfs_clear_2
+
+ /* if DLL is currently off, turn it back on. */
+ cmp r9, #0
+ beq update_calibration_only
+
+ /* issue zq calibration command */
+ ldr r0, [r5, #MMDC0_MPZQHWCTRL]
+ orr r0, r0, #0x3
+ str r0, [r5, #MMDC0_MPZQHWCTRL]
+ ldr r2, =MMDC1_MPZQHWCTRL
+ str r0, [r5, r2]
+
+ /* enable DQS gating. */
+ ldr r2, =MMDC0_MPDGCTRL0
+ ldr r0, [r5, r2]
+ bic r0, r0, #(1 << 29)
+ str r0, [r5, r2]
+
+ ldr r2, =MMDC1_MPDGCTRL0
+ ldr r0, [r5, r2]
+ bic r0, r0, #(1 << 29)
+ str r0, [r5, r2]
+
+ /* force measure. */
+ ldr r0, =0x00000800
+ str r0, [r5, #MMDC0_MPMUR0]
+ ldr r2, =MMDC1_MPMUR0
+ str r0, [r5, r2]
+
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r0, [r5, #MMDC0_MPMUR0]
+ and r0, r0, #0x800
+ ldr r1, [r5, r2]
+ and r1, r1, #0x800
+ orr r0, r0, r1
+ cmp r0, #0x0
+ bne 1b
+
+ /* disable dqs pull down in the IOMUX. */
+ ldr r1, [r11]
+ add r11, r11, #8
+update_iomux1:
+ ldr r0, [r11, #0x0]
+ ldr r3, [r11, #0x4]
+ str r3, [r7, r0]
+ add r11, r11, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_iomux1
+
+ /* config MMDC timings to 528MHz. */
+ ldr r9, [r8]
+ add r8, r8, #8
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /* configure ddr devices to dll on, odt. */
+ ldr r0, =0x00048031
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x00048039
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /* delay for while. */
+ ldr r1, =4
+delay7:
+ ldr r2, =0
+cont7:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont7
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay7
+
+ /* reset dll. */
+ ldr r0, =0x09408030
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x09408038
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /* delay for while. */
+ ldr r1, =100
+delay8:
+ ldr r2, =0
+cont8:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay8
+
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, =0x00428031
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x00428039
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ /* issue a zq command. */
+ ldr r0, =0x04008040
+ str r0, [r5, #MMDC0_MDSCR]
+
+ ldr r0, =0x04008048
+ str r0, [r5, #MMDC0_MDSCR]
+
+ /* MMDC ODT enable. */
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+
+ ldr r2, =0x4818
+ str r3, [r5, r2]
+
+ /* delay for while. */
+ ldr r1, =40
+delay15:
+ ldr r2, =0
+cont15:
+ ldr r0, [r5, r2]
+ add r2, r2, #4
+ cmp r2, #16
+ bne cont15
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt delay15
+
+ /* enable MMDC power down timer. */
+ ldr r0, [r5, #MMDC0_MDPDC]
+ orr r0, r0, #(0x55 << 8)
+ str r0, [r5, #MMDC0_MDPDC]
+
+ b update_calibration
+
+update_calibration_only:
+ ldr r1, [r8]
+ sub r1, r1, #7
+ add r8, r8, #64
+ b update_calib
+
+update_calibration:
+ /* write the new calibration values. */
+ mov r1, r9
+ sub r1, r1, #7
+
+update_calib:
+ ldr r0, [r8, #0x0]
+ ldr r3, [r8, #0x4]
+ str r3, [r5, r0]
+ add r8, r8, #8
+ sub r1, r1, #1
+ cmp r1, #0
+ bgt update_calib
+
+ /* perform a force measurement. */
+ ldr r0, =0x800
+ str r0, [r5, #MMDC0_MPMUR0]
+ ldr r2, =MMDC1_MPMUR0
+ str r0, [r5, r2]
+
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r0, [r5, #MMDC0_MPMUR0]
+ and r0, r0, #0x800
+ ldr r1, [r5, r2]
+ and r1, r1, #0x800
+ orr r0, r0, r1
+ cmp r0, #0x0
+ bne 1b
+
+ /* clear SBS - unblock DDR accesses. */
+ ldr r0, [r5, #MMDC0_MADPCR0]
+ bic r0, r0, #(1 << 8)
+ str r0, [r5, #MMDC0_MADPCR0]
+
+ is_mx6qp
+ bne 3f
+ /*
+ * Switch back to adopt_bp mode, set MMDC0_MAARCR
+ * bit25~26 to 2b'10.
+ */
+ ldr r0, [r5, #MMDC0_MAARCR]
+ bic r0, r0, #(0x3 << 25)
+ orr r0, r0, #(0x2 << 25)
+ str r0, [r5, #MMDC0_MAARCR]
+3:
+ mov r0, #0x0
+ str r0, [r5, #MMDC0_MDSCR]
+poll_conreq_clear_2:
+ ldr r0, [r5, #MMDC0_MDSCR]
+ and r0, r0, #(0x4 << 12)
+ cmp r0, #(0x4 << 12)
+ beq poll_conreq_clear_2
+
+done:
+ /* MMDC0_MAPSR adopt power down enable. */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ bic r0, r0, #0x01
+ str r0, [r5, #MMDC0_MAPSR]
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r1, [r12, #PL310_AUX_CTRL]
+ tst r1, #PL310_AUX_16WAY_BIT
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ mov r1, #0x00 /* 8 ways mask */
+ orrne r1, #0x0000 /* 16 ways mask */
+ add r5, r12, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r1, [r5], #PL310_LOCKDOWN_SZREG
+ str r1, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+
+ isb
+ dsb
+#endif
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ isb
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+ isb
+ dsb
+
+ /* restore registers */
+ ldmfd sp!, {r4-r12}
+ mov pc, lr
+
+ /*
+ * Add ltorg here to ensure that all
+ * literals are stored here and are
+ * within the text space.
+ */
+ .ltorg
+mx6_ddr3_freq_change_end:
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6sx.S b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
new file mode 100644
index 000000000000..1ac0d017bdf9
--- /dev/null
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+.globl imx6_up_ddr3_freq_change_start
+.globl imx6_up_ddr3_freq_change_end
+
+#define MMDC0_MDPDC 0x4
+#define MMDC0_MDCF0 0xc
+#define MMDC0_MDCF1 0x10
+#define MMDC0_MDMISC 0x18
+#define MMDC0_MDSCR 0x1c
+#define MMDC0_MAPSR 0x404
+#define MMDC0_MADPCR0 0x410
+#define MMDC0_MPZQHWCTRL 0x800
+#define MMDC0_MPODTCTRL 0x818
+#define MMDC0_MPDGCTRL0 0x83c
+#define MMDC0_MPMUR0 0x8b8
+
+#define CCM_CBCDR 0x14
+#define CCM_CBCMR 0x18
+#define CCM_CSCMR1 0x1c
+#define CCM_CDHIPR 0x48
+
+#define L2_CACHE_SYNC 0x730
+#define PL310_AUX_CTRL 0x104
+#define PL310_DCACHE_LOCKDOWN_BASE 0x900
+#define PL310_AUX_16WAY_BIT 0x10000
+#define PL310_LOCKDOWN_NBREGS 8
+#define PL310_LOCKDOWN_SZREG 4
+#define PL310_8WAYS_MASK 0x00FF
+#define PL310_16WAYS_UPPERMASK 0xFF00
+
+#define BUSFREQ_INFO_FREQ_OFFSET 0x0
+#define BUSFREQ_INFO_DDR_SETTINGS_OFFSET 0x4
+#define BUSFREQ_INFO_DLL_OFF_OFFSET 0x8
+#define BUSFREQ_INFO_IOMUX_OFFSETS_OFFSET 0xc
+#define BUSFREQ_INFO_MU_DELAY_OFFSET 0x10
+
+.extern iram_tlb_phys_addr
+
+ .align 3
+
+ /* Check if the cpu is cortex-a7 */
+ .macro is_ca7
+
+ /* Read the primary cpu number is MPIDR */
+ mrc p15, 0, r7, c0, c0, 0
+ ldr r8, =0xfff0
+ and r7, r7, r8
+ ldr r8, =0xc070
+ cmp r7, r8
+
+ .endm
+
+ .macro do_delay
+
+1:
+ ldr r9, =0
+2:
+ ldr r10, [r4, r9]
+ add r9, r9, #4
+ cmp r9, #16
+ bne 2b
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt 1b
+
+ .endm
+
+ .macro wait_for_ccm_handshake
+
+3:
+ ldr r8, [r5, #CCM_CDHIPR]
+ cmp r8, #0
+ bne 3b
+
+ .endm
+
+ .macro switch_to_400MHz
+
+ /* check whether periph2_clk is already from top path */
+ ldr r8, [r5, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_400m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r5, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_400m:
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r5, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_50MHz
+
+ /* check whether periph2_clk is already from top path */
+ ldr r8, [r5, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_50m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r5, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_50m:
+
+ /* fabric_mmdc_podf to 7 so that mmdc is 400 / 8 = 50MHz */
+ ldr r8, [r5, #CCM_CBCDR]
+ orr r8, r8, #(0x7 << 3)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_24MHz
+
+ /* periph2_clk2 sel to OSC_CLK */
+ ldr r8, [r5, #CCM_CBCMR]
+ orr r8, r8, #(1 << 20)
+ str r8, [r5, #CCM_CBCMR]
+
+ /* periph2_clk2_podf to 0 */
+ ldr r8, [r5, #CCM_CBCDR]
+ bic r8, r8, #0x7
+ str r8, [r5, #CCM_CBCDR]
+
+ /* periph2_clk sel to periph2_clk2 */
+ ldr r8, [r5, #CCM_CBCDR]
+ orr r8, r8, #(0x1 << 26)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r5, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r5, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+/*
+ * imx6_up_ddr3_freq_change
+ * Below code can be used by i.MX6SX and i.MX6UL.
+ *
+ * idle the processor (eg, wait for interrupt).
+ * make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(imx6_up_ddr3_freq_change)
+
+imx6_up_ddr3_freq_change_start:
+ stmfd sp!, {r4 - r11}
+
+ ldr r1, [r0, #BUSFREQ_INFO_DDR_SETTINGS_OFFSET]
+ ldr r2, [r0, #BUSFREQ_INFO_DLL_OFF_OFFSET]
+ ldr r3, [r0, #BUSFREQ_INFO_IOMUX_OFFSETS_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+ ldr r5, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r6, =IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR)
+
+ is_ca7
+ beq skip_disable_l2
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * make sure the L2 buffers are drained,
+ * sync operation on L2 drains the buffers.
+ */
+ ldr r8, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r7, [r8, #0x730]
+ cmp r7, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r7, #0x0
+ str r7, [r8, #L2_CACHE_SYNC]
+
+ /* Lock L2. */
+
+ ldr r9, [r8, #PL310_AUX_CTRL]
+ tst r9, #PL310_AUX_16WAY_BIT
+ mov r9, #PL310_8WAYS_MASK
+ orrne r9, #PL310_16WAYS_UPPERMASK
+ mov r10, #PL310_LOCKDOWN_NBREGS
+ add r11, r8, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r9, [r11], #PL310_LOCKDOWN_SZREG
+ str r9, [r11], #PL310_LOCKDOWN_SZREG
+ subs r10, r10, #1
+ bne 1b
+
+ /*
+ * The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+#endif
+
+skip_disable_l2:
+ /* disable automatic power saving. */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ orr r8, r8, #0x1
+ str r8, [r4, #MMDC0_MAPSR]
+
+ /* disable MMDC power down timer. */
+ ldr r8, [r4, #MMDC0_MDPDC]
+ bic r8, r8, #(0xff << 8)
+ str r8, [r4, #MMDC0_MDPDC]
+
+ /* delay for a while */
+ ldr r8, =4
+ do_delay
+
+ /* set CON_REG */
+ ldr r8, =0x8000
+ str r8, [r4, #MMDC0_MDSCR]
+poll_conreq_set_1:
+ ldr r8, [r4, #MMDC0_MDSCR]
+ and r8, r8, #(0x4 << 12)
+ cmp r8, #(0x4 << 12)
+ bne poll_conreq_set_1
+
+ /*
+ * if requested frequency is greater than
+ * 300MHz go to DLL on mode.
+ */
+ ldr r8, [r0, #BUSFREQ_INFO_FREQ_OFFSET]
+ ldr r9, =300000000
+ cmp r8, r9
+ bge dll_on_mode
+
+dll_off_mode:
+ /* if DLL is currently on, turn it off. */
+ cmp r2, #1
+ beq continue_dll_off_1
+
+ ldr r8, =0x00018031
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x00018039
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =10
+ do_delay
+
+continue_dll_off_1:
+ /* set DVFS - enter self refresh mode */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ orr r8, r8, #(1 << 21)
+ str r8, [r4, #MMDC0_MAPSR]
+
+ /* de-assert con_req */
+ mov r8, #0x0
+ str r8, [r4, #MMDC0_MDSCR]
+
+poll_dvfs_set_1:
+ ldr r8, [r4, #MMDC0_MAPSR]
+ and r8, r8, #(1 << 25)
+ cmp r8, #(1 << 25)
+ bne poll_dvfs_set_1
+
+ ldr r8, [r0, #BUSFREQ_INFO_FREQ_OFFSET]
+ ldr r9, =24000000
+ cmp r8, r9
+ beq switch_freq_24
+
+ switch_to_50MHz
+ b continue_dll_off_2
+
+switch_freq_24:
+ switch_to_24MHz
+
+continue_dll_off_2:
+ /* set SBS - block ddr accesses */
+ ldr r8, [r4, #MMDC0_MADPCR0]
+ orr r8, r8, #(1 << 8)
+ str r8, [r4, #MMDC0_MADPCR0]
+
+ /* clear DVFS - exit from self refresh mode */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ bic r8, r8, #(1 << 21)
+ str r8, [r4, #MMDC0_MAPSR]
+
+poll_dvfs_clear_1:
+ ldr r8, [r4, #MMDC0_MAPSR]
+ and r8, r8, #(1 << 25)
+ cmp r8, #(1 << 25)
+ beq poll_dvfs_clear_1
+
+ /* if DLL was previously on, continue DLL off routine. */
+ cmp r2, #1
+ beq continue_dll_off_3
+
+ ldr r8, =0x00018031
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x00018039
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x04208030
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x04208038
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x00088032
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x0008803A
+ str r8, [r4, #MMDC0_MDSCR]
+
+ /* delay for a while. */
+ ldr r8, =4
+ do_delay
+
+ ldr r8, [r4, #MMDC0_MDCF0]
+ bic r8, r8, #0xf
+ orr r8, r8, #0x3
+ str r8, [r4, #MMDC0_MDCF0]
+
+ ldr r8, [r4, #MMDC0_MDCF1]
+ bic r8, r8, #0x7
+ orr r8, r8, #0x4
+ str r8, [r4, #MMDC0_MDCF1]
+
+ ldr r8, [r4, #MMDC0_MDMISC]
+ bic r8, r8, #(0x3 << 16) /* walat = 0x1 */
+ orr r8, r8, #(0x1 << 16)
+ bic r8, r8, #(0x7 << 6) /* ralat = 0x2 */
+ orr r8, r8, #(0x2 << 6)
+ str r8, [r4, #MMDC0_MDMISC]
+
+ /* enable dqs pull down in the IOMUX. */
+ ldr r8, [r3]
+ add r3, r3, #8
+ ldr r9, =0x3028
+update_iomux:
+ ldr r10, [r3]
+ ldr r11, [r6, r10]
+ bic r11, r11, r9
+ orr r11, r11, #(0x3 << 12)
+ orr r11, r11, #0x28
+ str r11, [r6, r10]
+ add r3, r3, #8
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt update_iomux
+
+ /* ODT disabled. */
+ ldr r8, =0x0
+ str r8, [r4, #MMDC0_MPODTCTRL]
+
+ /* DQS gating disabled. */
+ ldr r8, [r4, #MMDC0_MPDGCTRL0]
+ orr r8, r8, #(1 << 29)
+ str r8, [r4, #MMDC0_MPDGCTRL0]
+
+ /* Add workaround for ERR005778.*/
+ /* double the original MU_UNIT_DEL_NUM. */
+ ldr r8, [r0, #BUSFREQ_INFO_MU_DELAY_OFFSET]
+ lsl r8, r8, #1
+
+ /* Bypass the automatic MU by setting the mu_byp_en */
+ ldr r10, [r4, #MMDC0_MPMUR0]
+ orr r10, r10, #0x400
+ /* Set the MU_BYP_VAL */
+ orr r10, r10, r8
+ str r10, [r4, #MMDC0_MPMUR0]
+
+ /* Now perform a force measure */
+ ldr r8, [r4, #MMDC0_MPMUR0]
+ orr r8, r8, #0x800
+ str r8, [r4, #MMDC0_MPMUR0]
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r8, [r4, #MMDC0_MPMUR0]
+ and r8, r8, #0x800
+ cmp r8, #0x0
+ bne 1b
+
+continue_dll_off_3:
+ /* clear SBS - unblock accesses to DDR. */
+ ldr r8, [r4, #MMDC0_MADPCR0]
+ bic r8, r8, #(0x1 << 8)
+ str r8, [r4, #MMDC0_MADPCR0]
+
+ mov r8, #0x0
+ str r8, [r4, #MMDC0_MDSCR]
+poll_conreq_clear_1:
+ ldr r8, [r4, #MMDC0_MDSCR]
+ and r8, r8, #(0x4 << 12)
+ cmp r8, #(0x4 << 12)
+ beq poll_conreq_clear_1
+
+ b done
+
+dll_on_mode:
+ /* assert DVFS - enter self refresh mode. */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ orr r8, r8, #(1 << 21)
+ str r8, [r4, #MMDC0_MAPSR]
+
+ /* de-assert CON_REQ. */
+ mov r8, #0x0
+ str r8, [r4, #MMDC0_MDSCR]
+
+ /* poll DVFS ack. */
+poll_dvfs_set_2:
+ ldr r8, [r4, #MMDC0_MAPSR]
+ and r8, r8, #(1 << 25)
+ cmp r8, #(1 << 25)
+ bne poll_dvfs_set_2
+
+ switch_to_400MHz
+
+ /* set SBS step-by-step mode. */
+ ldr r8, [r4, #MMDC0_MADPCR0]
+ orr r8, r8, #(1 << 8)
+ str r8, [r4, #MMDC0_MADPCR0]
+
+ /* clear DVFS - exit self refresh mode. */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ bic r8, r8, #(1 << 21)
+ str r8, [r4, #MMDC0_MAPSR]
+
+poll_dvfs_clear_2:
+ ldr r8, [r4, #MMDC0_MAPSR]
+ ands r8, r8, #(1 << 25)
+ bne poll_dvfs_clear_2
+
+ /* if DLL is currently off, turn it back on. */
+ cmp r2, #0
+ beq update_calibration_only
+
+ /* issue zq calibration command */
+ ldr r8, [r4, #MMDC0_MPZQHWCTRL]
+ orr r8, r8, #0x3
+ str r8, [r4, #MMDC0_MPZQHWCTRL]
+
+ /* enable DQS gating. */
+ ldr r10, =MMDC0_MPDGCTRL0
+ ldr r8, [r4, r10]
+ bic r8, r8, #(1 << 29)
+ str r8, [r4, r10]
+
+ /* Now perform a force measure */
+ ldr r8, =0x00000800
+ str r8, [r4, #MMDC0_MPMUR0]
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r8, [r4, #MMDC0_MPMUR0]
+ and r8, r8, #0x800
+ cmp r8, #0x0
+ bne 1b
+
+ /* disable dqs pull down in the IOMUX. */
+ ldr r8, [r3]
+ add r3, r3, #8
+update_iomux1:
+ ldr r10, [r3, #0x0]
+ ldr r11, [r3, #0x4]
+ str r11, [r6, r10]
+ add r3, r3, #8
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt update_iomux1
+
+ /* config MMDC timings to 400MHz. */
+ ldr r1, [r0, #BUSFREQ_INFO_DDR_SETTINGS_OFFSET]
+ ldr r7, [r1]
+ add r1, r1, #8
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ /* configure ddr devices to dll on, odt. */
+ ldr r8, =0x00028031
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x00028039
+ str r8, [r4, #MMDC0_MDSCR]
+
+ /* delay for while. */
+ ldr r8, =4
+ do_delay
+
+ /* reset dll. */
+ ldr r8, =0x09208030
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x09208038
+ str r8, [r4, #MMDC0_MDSCR]
+
+ /* delay for while. */
+ ldr r8, =100
+ do_delay
+
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ ldr r8, =0x00428031
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x00428039
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ /* issue a zq command. */
+ ldr r8, =0x04008040
+ str r8, [r4, #MMDC0_MDSCR]
+
+ ldr r8, =0x04008048
+ str r8, [r4, #MMDC0_MDSCR]
+
+ /* MMDC ODT enable. */
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+
+ /* delay for while. */
+ ldr r8, =40
+ do_delay
+
+ /* enable MMDC power down timer. */
+ ldr r8, [r4, #MMDC0_MDPDC]
+ orr r8, r8, #(0x55 << 8)
+ str r8, [r4, #MMDC0_MDPDC]
+
+ b update_calibration
+
+update_calibration_only:
+ ldr r8, [r1]
+ sub r8, r8, #7
+ add r1, r1, #64
+ b update_calib
+
+update_calibration:
+ /* write the new calibration values. */
+ mov r8, r7
+ sub r8, r8, #7
+
+update_calib:
+ ldr r10, [r1, #0x0]
+ ldr r11, [r1, #0x4]
+ str r11, [r4, r10]
+ add r1, r1, #8
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt update_calib
+
+ /* perform a force measurement. */
+ ldr r8, =0x800
+ str r8, [r4, #MMDC0_MPMUR0]
+ /* Wait for FRC_MSR to clear. */
+1:
+ ldr r8, [r4, #MMDC0_MPMUR0]
+ and r8, r8, #0x800
+ cmp r8, #0x0
+ bne 1b
+
+ /* clear SBS - unblock DDR accesses. */
+ ldr r8, [r4, #MMDC0_MADPCR0]
+ bic r8, r8, #(1 << 8)
+ str r8, [r4, #MMDC0_MADPCR0]
+
+ mov r8, #0x0
+ str r8, [r4, #MMDC0_MDSCR]
+poll_conreq_clear_2:
+ ldr r8, [r4, #MMDC0_MDSCR]
+ and r8, r8, #(0x4 << 12)
+ cmp r8, #(0x4 << 12)
+ beq poll_conreq_clear_2
+
+done:
+
+ /* MMDC0_MAPSR adopt power down enable. */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ bic r8, r8, #0x01
+ str r8, [r4, #MMDC0_MAPSR]
+
+ is_ca7
+ beq skip_enable_l2
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Unlock L2. */
+ ldr r8, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r9, [r8, #PL310_AUX_CTRL]
+ tst r9, #PL310_AUX_16WAY_BIT
+ mov r10, #PL310_LOCKDOWN_NBREGS
+ mov r9, #0x00 /* 8 ways mask */
+ orrne r9, #0x0000 /* 16 ways mask */
+ add r11, r8, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r9, [r11], #PL310_LOCKDOWN_SZREG
+ str r9, [r11], #PL310_LOCKDOWN_SZREG
+ subs r10, r10, #1
+ bne 1b
+
+#endif
+
+skip_enable_l2:
+ /* Enable L1 data cache. */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #0x4
+ mcr p15, 0, r7, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #0x800
+ mcr p15, 0, r7, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r7, =0x0
+ mcr p15, 0, r7, c7, c1, 6
+
+ /* restore registers */
+ ldmfd sp!, {r4 - r11}
+ mov pc, lr
+
+ /*
+ * Add ltorg here to ensure that all
+ * literals are stored here and are
+ * within the text space.
+ */
+ .ltorg
+imx6_up_ddr3_freq_change_end:
+ENDPROC(imx6_up_ddr3_freq_change)
diff --git a/arch/arm/mach-imx/ddr3_freq_imx7d.S b/arch/arm/mach-imx/ddr3_freq_imx7d.S
new file mode 100644
index 000000000000..9342e0d83f5e
--- /dev/null
+++ b/arch/arm/mach-imx/ddr3_freq_imx7d.S
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+#define DDRC_MSTR 0x0
+#define DDRC_STAT 0x4
+#define DDRC_MRCTRL0 0x10
+#define DDRC_MRCTRL1 0x14
+#define DDRC_MRSTAT 0x18
+#define DDRC_PWRCTL 0x30
+#define DDRC_RFSHCTL3 0x60
+#define DDRC_RFSHTMG 0x64
+#define DDRC_DBG1 0x304
+#define DDRC_SWCTL 0x320
+#define DDRC_SWSTAT 0x324
+#define DDRC_PSTAT 0x3fc
+#define DDRC_PCTRL_0 0x490
+#define DDRC_ZQCTL0 0x180
+#define DDRC_DFIMISC 0x1b0
+#define DDRC_DBGCAM 0x308
+#define DDRPHY_LP_CON0 0x18
+#define IOMUXC_GPR8 0x20
+#define DDRPHY_MDLL_CON0 0xb0
+#define DDRPHY_MDLL_CON1 0xb4
+#define DDRPHY_OFFSETD_CON0 0x50
+#define DDRPHY_OFFSETR_CON0 0x20
+#define DDRPHY_OFFSETR_CON1 0x24
+#define DDRPHY_OFFSETR_CON2 0x28
+#define DDRPHY_OFFSETW_CON0 0x30
+#define DDRPHY_OFFSETW_CON1 0x34
+#define DDRPHY_OFFSETW_CON2 0x38
+#define DDRPHY_CA_WLDSKEW_CON0 0x6c
+#define DDRPHY_CA_DSKEW_CON0 0x7c
+#define DDRPHY_CA_DSKEW_CON1 0x80
+#define DDRPHY_CA_DSKEW_CON2 0x84
+
+#define ANADIG_DIGPROG 0x800
+
+ .align 3
+
+ .macro switch_to_below_100m
+
+ ldr r7, =0x2
+ str r7, [r4, #DDRC_DBG1]
+
+ ldr r6, =0x36000000
+1:
+ ldr r7, [r4, #DDRC_DBGCAM]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 1b
+
+ ldr r6, =0x1
+2:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 2b
+
+ ldr r7, =0x10f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800010f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+3:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 3b
+
+ ldr r7, =0x20f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x8
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800020f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+4:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 4b
+
+ ldr r7, =0x10f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800010f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r7, =0x20
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x23
+5:
+ ldr r7, [r4, #DDRC_STAT]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 5b
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_SWCTL]
+
+ ldr r7, =0x03048001
+ str r7, [r4, #DDRC_MSTR]
+
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_SWCTL]
+
+ ldr r6, =0x1
+6:
+ ldr r7, [r4, #DDRC_SWSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 6b
+
+ ldr r7, =0x10010100
+ str r7, [r5, #0x4]
+
+ ldr r6, =24000000
+ cmp r0, r6
+ beq 25f
+
+ ldr r7, =0x000B000D
+ str r7,[r4, #DDRC_RFSHTMG]
+ b 7f
+
+25:
+ ldr r7, =0x00030004
+ str r7,[r4, #DDRC_RFSHTMG]
+
+ /* dram alt sel set to OSC */
+ ldr r7, =0x10000000
+ ldr r8, =0xa080
+ str r7, [r2, r8]
+ /* dram root set to from dram alt, div by 1 */
+ ldr r7, =0x11000000
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+ b 8f
+7:
+ /* dram alt sel set to pfd0_392m */
+ ldr r7, =0x15000000
+ ldr r8, =0xa080
+ str r7, [r2, r8]
+ /* dram root set to from dram alt, div by 4 */
+ ldr r7, =0x11000003
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+8:
+ ldr r7, =0x202ffd0
+ str r7, [r5, #DDRPHY_MDLL_CON0]
+
+ ldr r7, =0x1000007f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r7, =0x7f7f7f7f
+ str r7, [r5, #DDRPHY_OFFSETR_CON0]
+ str r7, [r5, #DDRPHY_OFFSETR_CON1]
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETR_CON2]
+
+ ldr r7, =0x7f7f7f7f
+ str r7, [r5, #DDRPHY_OFFSETW_CON0]
+ str r7, [r5, #DDRPHY_OFFSETW_CON1]
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETW_CON2]
+
+ ldr r7, [r9, #ANADIG_DIGPROG]
+ and r7, r7, #0x11
+ cmp r7, #0x11
+ bne 20f
+
+ ldr r7, =0x0
+ str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
+ ldr r7, =0x60606060
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x00006060
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+ b 21f
+20:
+ ldr r7, =0x0
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+21:
+ ldr r7, =0x1100007f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+ ldr r7, =0x1000007f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x1
+9:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 9b
+
+ ldr r7, =0xf0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x820
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800000f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+10:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 10b
+
+ ldr r7, =0x800020
+ str r7, [r4, #DDRC_ZQCTL0]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_DBG1]
+
+ /* enable auto self-refresh */
+ ldr r7, [r4, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r4, #DDRC_PWRCTL]
+
+ .endm
+
+ .macro switch_to_533m
+
+ ldr r7, =0x2
+ str r7, [r4, #DDRC_DBG1]
+
+ ldr r7, =0x78
+ str r7, [r3, #IOMUXC_GPR8]
+ orr r7, r7, #0x100
+ str r7, [r3, #IOMUXC_GPR8]
+
+ ldr r6, =0x30000000
+11:
+ ldr r7, [r4, #DDRC_DBGCAM]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 11b
+
+ ldr r6, =0x1
+12:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 12b
+
+ ldr r7, =0x10f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800010f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r7, =0x20
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x23
+13:
+ ldr r7, [r4, #DDRC_STAT]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 13b
+
+ ldr r7, =0x03040001
+ str r7, [r4, #DDRC_MSTR]
+
+ ldr r7, =0x40800020
+ str r7, [r4, #DDRC_ZQCTL0]
+
+
+ ldr r7, =0x10210100
+ str r7, [r5, #0x4]
+
+ ldr r7, =0x00040046
+ str r7, [r4, #DDRC_RFSHTMG]
+
+ /* dram root set to from dram main, div by 2 */
+ ldr r7, =0x10000001
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+
+ ldr r7, =0x1010007e
+ str r7, [r5, #DDRPHY_MDLL_CON0]
+
+ ldr r7, =0x10000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_OFFSETR_CON0]
+ str r7, [r5, #DDRPHY_OFFSETR_CON1]
+ ldr r7, =0x8
+ str r7, [r5, #DDRPHY_OFFSETR_CON2]
+
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_OFFSETW_CON0]
+ str r7, [r5, #DDRPHY_OFFSETW_CON1]
+ ldr r7, =0x8
+ str r7, [r5, #DDRPHY_OFFSETW_CON2]
+
+ ldr r7, [r9, #ANADIG_DIGPROG]
+ and r7, r7, #0x11
+ cmp r7, #0x11
+ bne 22f
+
+ ldr r7, =0x40404040
+ str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
+ ldr r7, =0x18181818
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x40401818
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+ b 23f
+22:
+ ldr r7, =0x0
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+23:
+ ldr r7, =0x11000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+ ldr r7, =0x10000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r6, =0x4
+14:
+ ldr r7, [r5, #DDRPHY_MDLL_CON1]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 14b
+
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_RFSHCTL3]
+ ldr r7, =0x3
+ str r7, [r4, #DDRC_RFSHCTL3]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x1
+15:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 15b
+
+ ldr r7, =0x10f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800010f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+16:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 16b
+
+ ldr r7, =0xf0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x930
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800000f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_RFSHCTL3]
+ ldr r7, =0x2
+ str r7, [r4, #DDRC_RFSHCTL3]
+
+ ldr r6, =0x1
+17:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 17b
+
+ ldr r7, =0xf0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x930
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800000f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+18:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 18b
+
+ ldr r7, =0x20f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x408
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800020f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r6, =0x1
+19:
+ ldr r7, [r4, #DDRC_MRSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 19b
+
+ ldr r7, =0x10f0
+ str r7, [r4, #DDRC_MRCTRL0]
+ ldr r7, =0x4
+ str r7, [r4, #DDRC_MRCTRL1]
+ ldr r7, =0x800010f0
+ str r7, [r4, #DDRC_MRCTRL0]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_DBG1]
+
+ /* enable auto self-refresh */
+ ldr r7, [r4, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r4, #DDRC_PWRCTL]
+
+ .endm
+
+ENTRY(imx7d_ddr3_freq_change)
+ push {r2 - r9}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ ldr r2, =IMX_IO_P2V(MX7D_CCM_BASE_ADDR)
+ ldr r3, =IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR)
+ ldr r4, =IMX_IO_P2V(MX7D_DDRC_BASE_ADDR)
+ ldr r5, =IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR)
+ ldr r9, =IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR)
+
+ ldr r6, =100000000
+ cmp r0, r6
+ bgt set_to_533m
+
+set_to_below_100m:
+ switch_to_below_100m
+ b done
+
+set_to_533m:
+ switch_to_533m
+ b done
+
+done:
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* Restore registers */
+ pop {r2 - r9}
+ mov pc, lr
+ .ltorg
+ENDPROC(imx7d_ddr3_freq_change)
diff --git a/arch/arm/mach-imx/ddrc.c b/arch/arm/mach-imx/ddrc.c
new file mode 100644
index 000000000000..9c7f627d465e
--- /dev/null
+++ b/arch/arm/mach-imx/ddrc.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * 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/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#include "hardware.h"
+
+#define DDRC_MSTR 0x0
+#define BM_DDRC_MSTR_DDR3 0x1
+#define BM_DDRC_MSTR_LPDDR2 0x4
+#define BM_DDRC_MSTR_LPDDR3 0x8
+
+static int ddr_type;
+
+static int imx_ddrc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ void __iomem *ddrc_base, *reg;
+ u32 val;
+
+ ddrc_base = of_iomap(np, 0);
+ WARN_ON(!ddrc_base);
+
+ reg = ddrc_base + DDRC_MSTR;
+ /* Get ddr type */
+ val = readl_relaxed(reg);
+ val &= (BM_DDRC_MSTR_DDR3 | BM_DDRC_MSTR_LPDDR2
+ | BM_DDRC_MSTR_LPDDR3);
+
+ switch (val) {
+ case BM_DDRC_MSTR_DDR3:
+ pr_info("DDR type is DDR3!\n");
+ ddr_type = IMX_DDR_TYPE_DDR3;
+ break;
+ case BM_DDRC_MSTR_LPDDR2:
+ pr_info("DDR type is LPDDR2!\n");
+ ddr_type = IMX_DDR_TYPE_LPDDR2;
+ break;
+ case BM_DDRC_MSTR_LPDDR3:
+ pr_info("DDR type is LPDDR3!\n");
+ ddr_type = IMX_DDR_TYPE_LPDDR3;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int imx_ddrc_get_ddr_type(void)
+{
+ return ddr_type;
+}
+
+static struct of_device_id imx_ddrc_dt_ids[] = {
+ { .compatible = "fsl,imx7-ddrc", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_ddrc_driver = {
+ .driver = {
+ .name = "imx-ddrc",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_ddrc_dt_ids,
+ },
+ .probe = imx_ddrc_probe,
+};
+
+static int __init imx_ddrc_init(void)
+{
+ return platform_driver_register(&imx_ddrc_driver);
+}
+postcore_initcall(imx_ddrc_init);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index b5b557fe2c49..838d93381c07 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -14,22 +14,153 @@
#include "common.h"
#include "hardware.h"
-#define GPC_CNTR 0x0
+#define GPC_CNTR 0x000
+#define GPC_CNTR_L2_PGE 22
+
#define GPC_IMR1 0x008
+#define GPC_PGC_MF_PDN 0x220
#define GPC_PGC_CPU_PDN 0x2a0
#define GPC_PGC_CPU_PUPSCR 0x2a4
#define GPC_PGC_CPU_PDNSCR 0x2a8
#define GPC_PGC_SW2ISO_SHIFT 0x8
#define GPC_PGC_SW_SHIFT 0x0
-
-#define GPC_CNTR_L2_PGE_SHIFT 22
+#define GPC_M4_LPSR 0x2c
+#define GPC_M4_LPSR_M4_SLEEPING_SHIFT 4
+#define GPC_M4_LPSR_M4_SLEEPING_MASK 0x1
+#define GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_MASK 0x1
+#define GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_SHIFT 0
+#define GPC_M4_LPSR_M4_SLEEP_HOLD_ACK_MASK 0x1
+#define GPC_M4_LPSR_M4_SLEEP_HOLD_ACK_SHIFT 1
+
+#define GPC_PGC_CPU_SW_SHIFT 0
+#define GPC_PGC_CPU_SW_MASK 0x3f
+#define GPC_PGC_CPU_SW2ISO_SHIFT 8
+#define GPC_PGC_CPU_SW2ISO_MASK 0x3f
#define IMR_NUM 4
#define GPC_MAX_IRQS (IMR_NUM * 32)
+/* for irq #74 and #75 */
+#define GPC_USB_VBUS_WAKEUP_IRQ_MASK 0xc00
+
+/* for irq #150 and #151 */
+#define GPC_ENET_WAKEUP_IRQ_MASK 0xC00000
+
static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
+static u32 gpc_mf_irqs[IMR_NUM];
+static u32 gpc_mf_request_on[IMR_NUM];
+static DEFINE_SPINLOCK(gpc_lock);
+
+void imx_gpc_add_m4_wake_up_irq(u32 hwirq, bool enable)
+{
+ unsigned int idx = hwirq / 32;
+ unsigned long flags;
+ u32 mask;
+
+ /* Sanity check for SPI irq */
+ if (hwirq < 32)
+ return;
+
+ mask = 1 << hwirq % 32;
+ spin_lock_irqsave(&gpc_lock, flags);
+ gpc_wake_irqs[idx] = enable ? gpc_wake_irqs[idx] | mask :
+ gpc_wake_irqs[idx] & ~mask;
+ spin_unlock_irqrestore(&gpc_lock, flags);
+}
+
+void imx_gpc_hold_m4_in_sleep(void)
+{
+ int val;
+ unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+ /* wait M4 in wfi before asserting hold request */
+ while (!imx_gpc_is_m4_sleeping())
+ if (time_after(jiffies, timeout))
+ pr_err("M4 is NOT in expected sleep!\n");
+
+ val = readl_relaxed(gpc_base + GPC_M4_LPSR);
+ val &= ~(GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_MASK <<
+ GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_SHIFT);
+ writel_relaxed(val, gpc_base + GPC_M4_LPSR);
+
+ timeout = jiffies + msecs_to_jiffies(500);
+ while (readl_relaxed(gpc_base + GPC_M4_LPSR)
+ & (GPC_M4_LPSR_M4_SLEEP_HOLD_ACK_MASK <<
+ GPC_M4_LPSR_M4_SLEEP_HOLD_ACK_SHIFT))
+ if (time_after(jiffies, timeout))
+ pr_err("Wait M4 hold ack timeout!\n");
+}
+
+void imx_gpc_release_m4_in_sleep(void)
+{
+ int val;
+
+ val = readl_relaxed(gpc_base + GPC_M4_LPSR);
+ val |= GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_MASK <<
+ GPC_M4_LPSR_M4_SLEEP_HOLD_REQ_SHIFT;
+ writel_relaxed(val, gpc_base + GPC_M4_LPSR);
+}
+
+unsigned int imx_gpc_is_m4_sleeping(void)
+{
+ if (readl_relaxed(gpc_base + GPC_M4_LPSR) &
+ (GPC_M4_LPSR_M4_SLEEPING_MASK <<
+ GPC_M4_LPSR_M4_SLEEPING_SHIFT))
+ return 1;
+
+ return 0;
+}
+
+bool imx_gpc_usb_wakeup_enabled(void)
+{
+ if (!(cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll()))
+ return false;
+
+ /*
+ * for SoC later than i.MX6SX, USB vbus wakeup
+ * only needs weak 2P5 on, stop_mode_config is
+ * NOT needed, so we check if is USB vbus wakeup
+ * is enabled(assume irq #74 and #75) to decide
+ * if to keep weak 2P5 on.
+ */
+ if (gpc_wake_irqs[1] & GPC_USB_VBUS_WAKEUP_IRQ_MASK)
+ return true;
+
+ return false;
+}
+
+bool imx_gpc_enet_wakeup_enabled(void)
+{
+ if (!cpu_is_imx6q())
+ return false;
+
+ if (gpc_wake_irqs[3] & GPC_ENET_WAKEUP_IRQ_MASK)
+ return true;
+
+ return false;
+}
+
+unsigned int imx_gpc_is_mf_mix_off(void)
+{
+ return readl_relaxed(gpc_base + GPC_PGC_MF_PDN);
+}
+
+static void imx_gpc_mf_mix_off(void)
+{
+ int i;
+
+ for (i = 0; i < IMR_NUM; i++)
+ if (((gpc_wake_irqs[i] | gpc_mf_request_on[i]) &
+ gpc_mf_irqs[i]) != 0)
+ return;
+
+ pr_info("Turn off M/F mix!\n");
+ /* turn off mega/fast mix */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_MF_PDN);
+}
void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
{
@@ -53,9 +184,9 @@ void imx_gpc_set_l2_mem_power_in_lpm(bool power_off)
u32 val;
val = readl_relaxed(gpc_base + GPC_CNTR);
- val &= ~(1 << GPC_CNTR_L2_PGE_SHIFT);
+ val &= ~(1 << GPC_CNTR_L2_PGE);
if (power_off)
- val |= 1 << GPC_CNTR_L2_PGE_SHIFT;
+ val |= 1 << GPC_CNTR_L2_PGE;
writel_relaxed(val, gpc_base + GPC_CNTR);
}
@@ -64,6 +195,11 @@ void imx_gpc_pre_suspend(bool arm_power_off)
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
+ /* power down the mega-fast power domain */
+ if ((cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll()) && arm_power_off)
+ imx_gpc_mf_mix_off();
+
/* Tell GPC to power off ARM core when suspend */
if (arm_power_off)
imx_gpc_set_arm_power_in_lpm(arm_power_off);
@@ -81,6 +217,10 @@ void imx_gpc_post_resume(void)
/* Keep ARM core powered on for other low-power modes */
imx_gpc_set_arm_power_in_lpm(false);
+ /* Keep M/F mix powered on for other low-power modes */
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ writel_relaxed(0x0, gpc_base + GPC_PGC_MF_PDN);
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
@@ -89,11 +229,14 @@ void imx_gpc_post_resume(void)
static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
{
unsigned int idx = d->hwirq / 32;
+ unsigned long flags;
u32 mask;
mask = 1 << d->hwirq % 32;
+ spin_lock_irqsave(&gpc_lock, flags);
gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
gpc_wake_irqs[idx] & ~mask;
+ spin_unlock_irqrestore(&gpc_lock, flags);
/*
* Do *not* call into the parent, as the GIC doesn't have any
@@ -225,11 +368,78 @@ static const struct irq_domain_ops imx_gpc_domain_ops = {
.free = irq_domain_free_irqs_common,
};
+int imx_gpc_mf_power_on(unsigned int irq, unsigned int on)
+{
+ struct irq_desc *d = irq_to_desc(irq);
+ unsigned int idx = d->irq_data.hwirq / 32;
+ unsigned long flags;
+ u32 mask;
+
+ mask = 1 << (d->irq_data.hwirq % 32);
+ spin_lock_irqsave(&gpc_lock, flags);
+ gpc_mf_request_on[idx] = on ? gpc_mf_request_on[idx] | mask :
+ gpc_mf_request_on[idx] & ~mask;
+ spin_unlock_irqrestore(&gpc_lock, flags);
+
+ return 0;
+}
+
+int imx_gpc_mf_request_on(unsigned int irq, unsigned int on)
+{
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll())
+ return imx_gpc_mf_power_on(irq, on);
+ else if (cpu_is_imx7d())
+ return imx_gpcv2_mf_power_on(irq, on);
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(imx_gpc_mf_request_on);
+
+void imx_gpc_switch_pupscr_clk(bool flag)
+{
+ static u32 pupscr_sw2iso, pupscr_sw;
+ u32 ratio, pupscr = readl_relaxed(gpc_base + GPC_PGC_CPU_PUPSCR);
+
+ if (flag) {
+ /* save the init clock setting IPG/2048 for IPG@66Mhz */
+ pupscr_sw2iso = (pupscr >> GPC_PGC_CPU_SW2ISO_SHIFT) &
+ GPC_PGC_CPU_SW2ISO_MASK;
+ pupscr_sw = (pupscr >> GPC_PGC_CPU_SW_SHIFT) &
+ GPC_PGC_CPU_SW_MASK;
+ /*
+ * i.MX6UL TO1.0 ARM power up uses IPG/2048 as clock source,
+ * from TO1.1, PGC_CPU_PUPSCR bit [5] is re-defined to switch
+ * clock to IPG/32, enable this bit to speed up the ARM power
+ * up process in low power idle case(IPG@1.5Mhz). So the sw and
+ * sw2iso need to be adjusted as below:
+ * sw_new(sw2iso_new) = (2048 * 1.5 / 66 * 32) * sw(sw2iso)
+ */
+ ratio = 3072 / (66 * 32);
+ pupscr &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT |
+ GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
+ pupscr |= (ratio * pupscr_sw + 1) << GPC_PGC_CPU_SW_SHIFT |
+ 1 << 5 | (ratio * pupscr_sw2iso + 1) <<
+ GPC_PGC_CPU_SW2ISO_SHIFT;
+ writel_relaxed(pupscr, gpc_base + GPC_PGC_CPU_PUPSCR);
+ } else {
+ /* restore back after exit from low power idle */
+ pupscr &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT |
+ GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
+ pupscr |= pupscr_sw << GPC_PGC_CPU_SW_SHIFT |
+ pupscr_sw2iso << GPC_PGC_CPU_SW2ISO_SHIFT;
+ writel_relaxed(pupscr, gpc_base + GPC_PGC_CPU_PUPSCR);
+ }
+}
+
static int __init imx_gpc_init(struct device_node *node,
struct device_node *parent)
{
struct irq_domain *parent_domain, *domain;
int i;
+ u32 val;
+ u32 cpu_pupscr_sw2iso, cpu_pupscr_sw;
+ u32 cpu_pdnscr_iso2sw, cpu_pdnscr_iso;
if (!parent) {
pr_err("%pOF: no parent, giving up\n", node);
@@ -258,12 +468,70 @@ static int __init imx_gpc_init(struct device_node *node,
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+ /* Read supported wakeup source in M/F domain */
+ if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6ulz() || cpu_is_imx6sll()) {
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 0,
+ &gpc_mf_irqs[0]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 1,
+ &gpc_mf_irqs[1]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 2,
+ &gpc_mf_irqs[2]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 3,
+ &gpc_mf_irqs[3]);
+ if (!(gpc_mf_irqs[0] | gpc_mf_irqs[1] |
+ gpc_mf_irqs[2] | gpc_mf_irqs[3]))
+ pr_info("No wakeup source in Mega/Fast domain found!\n");
+ }
+
+ /* clear the L2_PGE bit on i.MX6SLL */
+ if (cpu_is_imx6sll()) {
+ val = readl_relaxed(gpc_base + GPC_CNTR);
+ val &= ~(1 << GPC_CNTR_L2_PGE);
+ writel_relaxed(val, gpc_base + GPC_CNTR);
+ }
+
/*
* Clear the OF_POPULATED flag set in of_irq_init so that
* later the GPC power domain driver will not be skipped.
*/
of_node_clear_flag(node, OF_POPULATED);
+ /*
+ * If there are CPU isolation timing settings in dts,
+ * update them according to dts, otherwise, keep them
+ * with default value in registers.
+ */
+ cpu_pupscr_sw2iso = cpu_pupscr_sw =
+ cpu_pdnscr_iso2sw = cpu_pdnscr_iso = 0;
+
+ /* Read CPU isolation setting for GPC */
+ of_property_read_u32(node, "fsl,cpu_pupscr_sw2iso", &cpu_pupscr_sw2iso);
+ of_property_read_u32(node, "fsl,cpu_pupscr_sw", &cpu_pupscr_sw);
+ of_property_read_u32(node, "fsl,cpu_pdnscr_iso2sw", &cpu_pdnscr_iso2sw);
+ of_property_read_u32(node, "fsl,cpu_pdnscr_iso", &cpu_pdnscr_iso);
+
+ /* Return if no property found in dtb */
+ if ((cpu_pupscr_sw2iso | cpu_pupscr_sw
+ | cpu_pdnscr_iso2sw | cpu_pdnscr_iso) == 0)
+ return 0;
+
+ /* Update CPU PUPSCR timing if it is defined in dts */
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_PUPSCR);
+ val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
+ val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT);
+ val |= cpu_pupscr_sw2iso << GPC_PGC_CPU_SW2ISO_SHIFT;
+ val |= cpu_pupscr_sw << GPC_PGC_CPU_SW_SHIFT;
+ writel_relaxed(val, gpc_base + GPC_PGC_CPU_PUPSCR);
+
+ /* Update CPU PDNSCR timing if it is defined in dts */
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_PDNSCR);
+ val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
+ val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT);
+ val |= cpu_pdnscr_iso2sw << GPC_PGC_CPU_SW2ISO_SHIFT;
+ val |= cpu_pdnscr_iso << GPC_PGC_CPU_SW_SHIFT;
+ writel_relaxed(val, gpc_base + GPC_PGC_CPU_PDNSCR);
+
return 0;
}
IRQCHIP_DECLARE(imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);
diff --git a/arch/arm/mach-imx/gpcv2.c b/arch/arm/mach-imx/gpcv2.c
new file mode 100644
index 000000000000..3e8ab91cb97f
--- /dev/null
+++ b/arch/arm/mach-imx/gpcv2.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regulator/consumer.h>
+
+#include "common.h"
+#include "hardware.h"
+
+#define IMR_NUM 4
+#define GPC_MAX_IRQS (IMR_NUM * 32)
+#define GPC_LPCR_A7_BSC 0x0
+#define GPC_LPCR_A7_AD 0x4
+#define GPC_LPCR_M4 0x8
+#define GPC_SLPCR 0x14
+#define GPC_MLPCR 0x20
+#define GPC_PGC_ACK_SEL_A7 0x24
+#define GPC_MISC 0x2c
+#define GPC_IMR1_CORE0 0x30
+#define GPC_IMR1_CORE1 0x40
+#define GPC_IMR1_M4 0x50
+#define GPC_SLOT0_CFG 0xb0
+#define GPC_PGC_CPU_MAPPING 0xec
+#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
+#define GPC_PU_PGC_SW_PUP_REQ 0xf8
+#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
+#define GPC_PU_PGC_SW_PDN_REQ 0x104
+#define GPC_GTOR 0x124
+#define GPC_PGC_C0 0x800
+#define GPC_PGC_C0_PUPSCR 0x804
+#define GPC_PGC_SCU_TIMING 0x890
+#define GPC_PGC_C1 0x840
+#define GPC_PGC_C1_PUPSCR 0x844
+#define GPC_PGC_SCU 0x880
+#define GPC_PGC_FM 0xa00
+
+#define BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP 0x70000000
+#define BM_LPCR_A7_BSC_CPU_CLK_ON_LPM 0x4000
+#define BM_LPCR_A7_BSC_LPM1 0xc
+#define BM_LPCR_A7_BSC_LPM0 0x3
+#define BP_LPCR_A7_BSC_LPM1 2
+#define BP_LPCR_A7_BSC_LPM0 0
+#define BM_LPCR_M4_MASK_DSM_TRIGGER 0x80000000
+#define BM_SLPCR_EN_DSM 0x80000000
+#define BM_SLPCR_RBC_EN 0x40000000
+#define BM_SLPCR_REG_BYPASS_COUNT 0x3f000000
+#define BM_SLPCR_VSTBY 0x4
+#define BM_SLPCR_SBYOS 0x2
+#define BM_SLPCR_BYPASS_PMIC_READY 0x1
+#define BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE 0x10000
+#define BM_LPCR_A7_AD_L2PGE 0x10000
+#define BM_LPCR_A7_AD_EN_C1_PUP 0x800
+#define BM_LPCR_A7_AD_EN_C1_IRQ_PUP 0x400
+#define BM_LPCR_A7_AD_EN_C0_PUP 0x200
+#define BM_LPCR_A7_AD_EN_C0_IRQ_PUP 0x100
+#define BM_LPCR_A7_AD_EN_PLAT_PDN 0x10
+#define BM_LPCR_A7_AD_EN_C1_PDN 0x8
+#define BM_LPCR_A7_AD_EN_C1_WFI_PDN 0x4
+#define BM_LPCR_A7_AD_EN_C0_PDN 0x2
+#define BM_LPCR_A7_AD_EN_C0_WFI_PDN 0x1
+
+#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
+#define BM_GPC_PGC_PCG 0x1
+#define BM_GPC_PGC_CORE_PUPSCR 0x7fff80
+
+#define BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK 0x80000000
+#define BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK 0x8000
+#define BM_GPC_MLPCR_MEMLP_CTL_DIS 0x1
+
+#define BP_LPCR_A7_BSC_IRQ_SRC 28
+
+#define MAX_SLOT_NUMBER 10
+#define A7_LPM_WAIT 0x5
+#define A7_LPM_STOP 0xa
+
+enum imx_gpc_slot {
+ CORE0_A7,
+ CORE1_A7,
+ SCU_A7,
+ FAST_MEGA_MIX,
+ MIPI_PHY,
+ PCIE_PHY,
+ USB_OTG1_PHY,
+ USB_OTG2_PHY,
+ USB_HSIC_PHY,
+ CORE0_M4,
+};
+
+static void __iomem *gpc_base;
+static u32 gpcv2_wake_irqs[IMR_NUM];
+static u32 gpcv2_saved_imrs[IMR_NUM];
+static u32 gpcv2_saved_imrs_m4[IMR_NUM];
+static u32 gpcv2_mf_irqs[IMR_NUM];
+static u32 gpcv2_mf_request_on[IMR_NUM];
+static DEFINE_SPINLOCK(gpcv2_lock);
+
+void imx_gpcv2_add_m4_wake_up_irq(u32 hwirq, bool enable)
+{
+ unsigned int idx = hwirq / 32;
+ unsigned long flags;
+ u32 mask;
+
+ /* Sanity check for SPI irq */
+ if (hwirq < 32)
+ return;
+
+ mask = 1 << hwirq % 32;
+ spin_lock_irqsave(&gpcv2_lock, flags);
+ gpcv2_wake_irqs[idx] = enable ? gpcv2_wake_irqs[idx] | mask :
+ gpcv2_wake_irqs[idx] & ~mask;
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+}
+
+static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ unsigned int idx = d->hwirq / 32;
+ unsigned long flags;
+ u32 mask;
+
+ BUG_ON(idx >= IMR_NUM);
+
+ mask = 1 << d->hwirq % 32;
+ spin_lock_irqsave(&gpcv2_lock, flags);
+ gpcv2_wake_irqs[idx] = on ? gpcv2_wake_irqs[idx] | mask :
+ gpcv2_wake_irqs[idx] & ~mask;
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+
+ return 0;
+}
+
+void imx_gpcv2_mask_all(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0;
+ int i;
+
+ for (i = 0; i < IMR_NUM; i++) {
+ gpcv2_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+ writel_relaxed(~0, reg_imr1 + i * 4);
+ }
+}
+
+void imx_gpcv2_restore_all(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0;
+ int i;
+
+ for (i = 0; i < IMR_NUM; i++)
+ writel_relaxed(gpcv2_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+void imx_gpcv2_hwirq_unmask(unsigned int hwirq)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = gpc_base + GPC_IMR1_CORE0 + (hwirq / 32) * 4;
+ val = readl_relaxed(reg);
+ val &= ~(1 << hwirq % 32);
+ writel_relaxed(val, reg);
+}
+
+void imx_gpcv2_hwirq_mask(unsigned int hwirq)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = gpc_base + GPC_IMR1_CORE0 + (hwirq / 32) * 4;
+ val = readl_relaxed(reg);
+ val |= 1 << (hwirq % 32);
+ writel_relaxed(val, reg);
+}
+
+static void imx_gpcv2_irq_unmask(struct irq_data *d)
+{
+ imx_gpcv2_hwirq_unmask(d->hwirq);
+ irq_chip_unmask_parent(d);
+}
+
+static void imx_gpcv2_irq_mask(struct irq_data *d)
+{
+ imx_gpcv2_hwirq_mask(d->hwirq);
+ irq_chip_mask_parent(d);
+}
+
+void imx_gpcv2_set_slot_ack(u32 index, enum imx_gpc_slot m_core,
+ bool mode, bool ack)
+{
+ u32 val;
+
+ if (index >= MAX_SLOT_NUMBER)
+ pr_err("Invalid slot index!\n");
+ /* set slot */
+ writel_relaxed(readl_relaxed(gpc_base + GPC_SLOT0_CFG + index * 4) |
+ ((mode + 1) << (m_core * 2)),
+ gpc_base + GPC_SLOT0_CFG + index * 4);
+
+ if (ack) {
+ /* set ack */
+ val = readl_relaxed(gpc_base + GPC_PGC_ACK_SEL_A7);
+ /* clear dummy ack */
+ val &= ~(1 << (15 + (mode ? 16 : 0)));
+ val |= 1 << (m_core + (mode ? 16 : 0));
+ writel_relaxed(val, gpc_base + GPC_PGC_ACK_SEL_A7);
+ }
+}
+
+void imx_gpcv2_set_lpm_mode(enum mxc_cpu_pwr_mode mode)
+{
+ unsigned long flags;
+ u32 val1, val2;
+
+ spin_lock_irqsave(&gpcv2_lock, flags);
+
+ val1 = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC);
+ val2 = readl_relaxed(gpc_base + GPC_SLPCR);
+
+ /* all cores' LPM settings must be same */
+ val1 &= ~(BM_LPCR_A7_BSC_LPM0 | BM_LPCR_A7_BSC_LPM1);
+
+ val1 |= BM_LPCR_A7_BSC_CPU_CLK_ON_LPM;
+
+ val2 &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
+ BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
+ /*
+ * GPC: When improper low-power sequence is used,
+ * the SoC enters low power mode before the ARM core executes WFI.
+ *
+ * Software workaround:
+ * 1) Software should trigger IRQ #32 (IOMUX) to be always pending
+ * by setting IOMUX_GPR1_IRQ.
+ * 2) Software should then unmask IRQ #32 in GPC before setting GPC
+ * Low-Power mode.
+ * 3) Software should mask IRQ #32 right after GPC Low-Power mode
+ * is set.
+ */
+ switch (mode) {
+ case WAIT_CLOCKED:
+ imx_gpcv2_hwirq_unmask(0);
+ break;
+ case WAIT_UNCLOCKED:
+ val1 |= A7_LPM_WAIT << BP_LPCR_A7_BSC_LPM0;
+ val1 &= ~BM_LPCR_A7_BSC_CPU_CLK_ON_LPM;
+ imx_gpcv2_hwirq_mask(0);
+ break;
+ case STOP_POWER_ON:
+ val1 |= A7_LPM_STOP << BP_LPCR_A7_BSC_LPM0;
+ val1 &= ~BM_LPCR_A7_BSC_CPU_CLK_ON_LPM;
+ val2 |= BM_SLPCR_EN_DSM;
+ val2 |= BM_SLPCR_RBC_EN;
+ val2 |= BM_SLPCR_BYPASS_PMIC_READY;
+ imx_gpcv2_hwirq_mask(0);
+ break;
+ case STOP_POWER_OFF:
+ val1 |= A7_LPM_STOP << BP_LPCR_A7_BSC_LPM0;
+ val1 &= ~BM_LPCR_A7_BSC_CPU_CLK_ON_LPM;
+ val2 |= BM_SLPCR_EN_DSM;
+ val2 |= BM_SLPCR_RBC_EN;
+ val2 |= BM_SLPCR_SBYOS;
+ val2 |= BM_SLPCR_VSTBY;
+ val2 |= BM_SLPCR_BYPASS_PMIC_READY;
+ imx_gpcv2_hwirq_mask(0);
+ break;
+ default:
+ return;
+ }
+ writel_relaxed(val1, gpc_base + GPC_LPCR_A7_BSC);
+ writel_relaxed(val2, gpc_base + GPC_SLPCR);
+
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+}
+
+void imx_gpcv2_set_plat_power_gate_by_lpm(bool pdn)
+{
+ u32 val = readl_relaxed(gpc_base + GPC_LPCR_A7_AD);
+
+ val &= ~(BM_LPCR_A7_AD_EN_PLAT_PDN | BM_LPCR_A7_AD_L2PGE);
+ if (pdn)
+ val |= BM_LPCR_A7_AD_EN_PLAT_PDN | BM_LPCR_A7_AD_L2PGE;
+
+ writel_relaxed(val, gpc_base + GPC_LPCR_A7_AD);
+}
+
+void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
+{
+ u32 val = readl_relaxed(gpc_base + offset) & (~BM_GPC_PGC_PCG);
+
+ if (enable)
+ val |= BM_GPC_PGC_PCG;
+
+ writel_relaxed(val, gpc_base + offset);
+}
+
+void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
+{
+ u32 val = readl_relaxed(gpc_base + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ));
+
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
+ val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
+ writel_relaxed(val, gpc_base + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ));
+
+ while ((readl_relaxed(gpc_base + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ)) &
+ BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7) != 0)
+ ;
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
+}
+
+void imx_gpcv2_set_cpu_power_gate_by_wfi(u32 cpu, bool pdn)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&gpcv2_lock, flags);
+ val = readl_relaxed(gpc_base + GPC_LPCR_A7_AD);
+
+ if (cpu == 0) {
+ if (pdn) {
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C0);
+ val |= BM_LPCR_A7_AD_EN_C0_WFI_PDN |
+ BM_LPCR_A7_AD_EN_C0_IRQ_PUP;
+ } else {
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C0);
+ val &= ~(BM_LPCR_A7_AD_EN_C0_WFI_PDN |
+ BM_LPCR_A7_AD_EN_C0_IRQ_PUP);
+ }
+ }
+ if (cpu == 1) {
+ if (pdn) {
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
+ val |= BM_LPCR_A7_AD_EN_C1_WFI_PDN |
+ BM_LPCR_A7_AD_EN_C1_IRQ_PUP;
+ } else {
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
+ val &= ~(BM_LPCR_A7_AD_EN_C1_WFI_PDN |
+ BM_LPCR_A7_AD_EN_C1_IRQ_PUP);
+ }
+ }
+ writel_relaxed(val, gpc_base + GPC_LPCR_A7_AD);
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+}
+
+void imx_gpcv2_set_cpu_power_gate_by_lpm(u32 cpu, bool pdn)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&gpcv2_lock, flags);
+
+ val = readl_relaxed(gpc_base + GPC_LPCR_A7_AD);
+ if (cpu == 0) {
+ if (pdn)
+ val |= BM_LPCR_A7_AD_EN_C0_PDN |
+ BM_LPCR_A7_AD_EN_C0_PUP;
+ else
+ val &= ~(BM_LPCR_A7_AD_EN_C0_PDN |
+ BM_LPCR_A7_AD_EN_C0_PUP);
+ }
+ if (cpu == 1) {
+ if (pdn)
+ val |= BM_LPCR_A7_AD_EN_C1_PDN |
+ BM_LPCR_A7_AD_EN_C1_PUP;
+ else
+ val &= ~(BM_LPCR_A7_AD_EN_C1_PDN |
+ BM_LPCR_A7_AD_EN_C1_PUP);
+ }
+
+ writel_relaxed(val, gpc_base + GPC_LPCR_A7_AD);
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+}
+
+void imx_gpcv2_set_cpu_power_gate_in_idle(bool pdn)
+{
+ unsigned long flags;
+ u32 cpu;
+
+ for_each_possible_cpu(cpu)
+ imx_gpcv2_set_cpu_power_gate_by_lpm(cpu, pdn);
+
+ spin_lock_irqsave(&gpcv2_lock, flags);
+
+ imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_C0);
+ if (num_online_cpus() > 1)
+ imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_C1);
+ imx_gpcv2_set_m_core_pgc(pdn, GPC_PGC_SCU);
+ imx_gpcv2_set_plat_power_gate_by_lpm(pdn);
+
+ if (pdn) {
+ imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false);
+ if (num_online_cpus() > 1)
+ imx_gpcv2_set_slot_ack(2, CORE1_A7, false, false);
+ imx_gpcv2_set_slot_ack(3, SCU_A7, false, true);
+ imx_gpcv2_set_slot_ack(6, SCU_A7, true, false);
+ if (num_online_cpus() > 1)
+ imx_gpcv2_set_slot_ack(6, CORE1_A7, true, false);
+ imx_gpcv2_set_slot_ack(6, CORE0_A7, true, true);
+ } else {
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 0 * 0x4);
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 2 * 0x4);
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 3 * 0x4);
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 6 * 0x4);
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 7 * 0x4);
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 8 * 0x4);
+ writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK |
+ BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK,
+ gpc_base + GPC_PGC_ACK_SEL_A7);
+ imx_gpcv2_enable_rbc(false);
+ }
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+}
+
+void imx_gpcv2_set_mix_phy_gate_by_lpm(u32 pdn_index, u32 pup_index)
+{
+ /* set power down slot */
+ writel_relaxed(1 << (FAST_MEGA_MIX * 2),
+ gpc_base + GPC_SLOT0_CFG + pdn_index * 4);
+
+ /* set power up slot */
+ writel_relaxed(1 << (FAST_MEGA_MIX * 2 + 1),
+ gpc_base + GPC_SLOT0_CFG + pup_index * 4);
+}
+
+unsigned int imx_gpcv2_is_mf_mix_off(void)
+{
+ return readl_relaxed(gpc_base + GPC_PGC_FM);
+}
+
+static void imx_gpcv2_mf_mix_off(void)
+{
+ int i;
+
+ for (i = 0; i < IMR_NUM; i++)
+ if (((gpcv2_wake_irqs[i] | gpcv2_mf_request_on[i]) &
+ gpcv2_mf_irqs[i]) != 0)
+ return;
+
+ pr_info("Turn off Mega/Fast mix in DSM\n");
+ imx_gpcv2_set_slot_ack(1, FAST_MEGA_MIX, false, false);
+ imx_gpcv2_set_slot_ack(5, FAST_MEGA_MIX, true, false);
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_FM);
+}
+
+int imx_gpcv2_mf_power_on(unsigned int irq, unsigned int on)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long hwirq = desc->irq_data.hwirq;
+ unsigned int idx = hwirq / 32;
+ unsigned long flags;
+ u32 mask = 1 << (hwirq % 32);
+
+ BUG_ON(idx >= IMR_NUM);
+
+ spin_lock_irqsave(&gpcv2_lock, flags);
+ gpcv2_mf_request_on[idx] = on ? gpcv2_mf_request_on[idx] | mask :
+ gpcv2_mf_request_on[idx] & ~mask;
+ spin_unlock_irqrestore(&gpcv2_lock, flags);
+
+ return 0;
+}
+
+void imx_gpcv2_enable_rbc(bool enable)
+{
+ u32 val;
+
+ /*
+ * need to mask all interrupts in GPC before
+ * operating RBC configurations
+ */
+ imx_gpcv2_mask_all();
+
+ /* configure RBC enable bit */
+ val = readl_relaxed(gpc_base + GPC_SLPCR);
+ val &= ~BM_SLPCR_RBC_EN;
+ val |= enable ? BM_SLPCR_RBC_EN : 0;
+ writel_relaxed(val, gpc_base + GPC_SLPCR);
+
+ /* configure RBC count */
+ val = readl_relaxed(gpc_base + GPC_SLPCR);
+ val &= ~BM_SLPCR_REG_BYPASS_COUNT;
+ val |= enable ? BM_SLPCR_REG_BYPASS_COUNT : 0;
+ writel(val, gpc_base + GPC_SLPCR);
+
+ /*
+ * need to delay at least 2 cycles of CKIL(32K)
+ * due to hardware design requirement, which is
+ * ~61us, here we use 65us for safe
+ */
+ udelay(65);
+
+ /* restore GPC interrupt mask settings */
+ imx_gpcv2_restore_all();
+}
+
+
+void imx_gpcv2_pre_suspend(bool arm_power_off)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0;
+ int i;
+
+ if (arm_power_off) {
+ imx_gpcv2_set_lpm_mode(STOP_POWER_OFF);
+ /* enable core0 power down/up with low power mode */
+ imx_gpcv2_set_cpu_power_gate_by_lpm(0, true);
+ /* enable plat power down with low power mode */
+ imx_gpcv2_set_plat_power_gate_by_lpm(true);
+
+ /*
+ * To avoid confuse, we use slot 0~4 for power down,
+ * slot 5~9 for power up.
+ *
+ * Power down slot sequence:
+ * Slot0 -> CORE0
+ * Slot1 -> Mega/Fast MIX
+ * Slot2 -> SCU
+ *
+ * Power up slot sequence:
+ * Slot5 -> Mega/Fast MIX
+ * Slot6 -> SCU
+ * Slot7 -> CORE0
+ */
+ imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false);
+ imx_gpcv2_set_slot_ack(2, SCU_A7, false, true);
+
+ if ((!imx_src_is_m4_enabled()) ||
+ (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()))
+ imx_gpcv2_mf_mix_off();;
+
+ imx_gpcv2_set_slot_ack(6, SCU_A7, true, false);
+ imx_gpcv2_set_slot_ack(6, CORE0_A7, true, true);
+
+ /* enable core0, scu */
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C0);
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_SCU);
+ } else {
+ imx_gpcv2_set_lpm_mode(STOP_POWER_ON);
+ }
+
+ for (i = 0; i < IMR_NUM; i++) {
+ gpcv2_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+ writel_relaxed(~gpcv2_wake_irqs[i], reg_imr1 + i * 4);
+ }
+}
+
+void imx_gpcv2_enable_wakeup_for_m4(void)
+{
+ void __iomem *reg_imr2 = gpc_base + GPC_IMR1_M4;
+ u32 i;
+
+ for (i = 0; i < IMR_NUM; i++) {
+ gpcv2_saved_imrs_m4[i] = readl_relaxed(reg_imr2 + i * 4);
+ writel_relaxed(~gpcv2_wake_irqs[i], reg_imr2 + i * 4);
+ }
+}
+
+void imx_gpcv2_disable_wakeup_for_m4(void)
+{
+ void __iomem *reg_imr2 = gpc_base + GPC_IMR1_M4;
+ u32 i;
+
+ for (i = 0; i < IMR_NUM; i++)
+ writel_relaxed(gpcv2_saved_imrs_m4[i], reg_imr2 + i * 4);
+}
+
+void imx_gpcv2_post_resume(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1_CORE0;
+ int i, val;
+
+ /* only external IRQs to wake up LPM and core 0/1 */
+ val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC);
+ val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP;
+ writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC);
+ /* mask m4 dsm trigger if M4 NOT enabled */
+ if (!imx_src_is_m4_enabled())
+ writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
+ BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
+ /* set mega/fast mix in A7 domain */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING);
+ /* set SCU timing */
+ writel_relaxed((0x59 << 10) | 0x5B | (0x2 << 20),
+ gpc_base + GPC_PGC_SCU_TIMING);
+
+ /* set C0/C1 power up timming per design requirement */
+ val = readl_relaxed(gpc_base + GPC_PGC_C0_PUPSCR);
+ val &= ~BM_GPC_PGC_CORE_PUPSCR;
+ val |= (0x1A << 7);
+ writel_relaxed(val, gpc_base + GPC_PGC_C0_PUPSCR);
+
+ val = readl_relaxed(gpc_base + GPC_PGC_C1_PUPSCR);
+ val &= ~BM_GPC_PGC_CORE_PUPSCR;
+ val |= (0x1A << 7);
+ writel_relaxed(val, gpc_base + GPC_PGC_C1_PUPSCR);
+
+ val = readl_relaxed(gpc_base + GPC_SLPCR);
+ val &= ~(BM_SLPCR_EN_DSM);
+ if (!imx_src_is_m4_enabled())
+ val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
+ BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
+ val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE;
+ writel_relaxed(val, gpc_base + GPC_SLPCR);
+
+ if (imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
+ /* disable memory low power mode */
+ val = readl_relaxed(gpc_base + GPC_MLPCR);
+ val |= BM_GPC_MLPCR_MEMLP_CTL_DIS;
+ writel_relaxed(val, gpc_base + GPC_MLPCR);
+ }
+
+ for (i = 0; i < IMR_NUM; i++)
+ writel_relaxed(gpcv2_saved_imrs[i], reg_imr1 + i * 4);
+
+ imx_gpcv2_set_lpm_mode(WAIT_CLOCKED);
+ imx_gpcv2_set_cpu_power_gate_by_lpm(0, false);
+ imx_gpcv2_set_plat_power_gate_by_lpm(false);
+
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C0);
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_SCU);
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_FM);
+ for (i = 0; i < MAX_SLOT_NUMBER; i++){
+ if (i == 1 || i == 5) /* skip slts m4 uses */
+ continue;
+ writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + i * 0x4);
+ }
+ writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK |
+ BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK,
+ gpc_base + GPC_PGC_ACK_SEL_A7);
+
+ /* disable RBC */
+ imx_gpcv2_enable_rbc(false);
+}
+
+static struct irq_chip imx_gpcv2_chip = {
+ .name = "GPCV2",
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_mask = imx_gpcv2_irq_mask,
+ .irq_unmask = imx_gpcv2_irq_unmask,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_wake = imx_gpcv2_irq_set_wake,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (irq_domain_get_of_node(domain) != controller)
+ return -EINVAL; /* Shouldn't happen, really... */
+ if (intsize != 3)
+ return -EINVAL; /* Not GIC compliant */
+ if (intspec[0] != 0)
+ return -EINVAL; /* No PPI should point to this domain */
+
+ *out_hwirq = intspec[1];
+ *out_type = intspec[2];
+ return 0;
+}
+
+static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
+ unsigned int irq,
+ unsigned int nr_irqs, void *data)
+{
+ struct irq_fwspec *fwspec = data;
+ struct irq_fwspec parent_fwspec;
+ irq_hw_number_t hwirq;
+ int i;
+
+ if (fwspec->param_count != 3)
+ return -EINVAL; /* Not GIC compliant */
+ if (fwspec->param[0] != 0)
+ return -EINVAL; /* No PPI should point to this domain */
+
+ hwirq = fwspec->param[1];
+ if (hwirq >= GPC_MAX_IRQS)
+ return -EINVAL; /* Can't deal with this */
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
+ &imx_gpcv2_chip, NULL);
+
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ parent_fwspec.param_count = 3;
+ parent_fwspec.param[0] = 0;
+ parent_fwspec.param[1] = hwirq;
+ parent_fwspec.param[2] = fwspec->param[2];
+
+ return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
+ &parent_fwspec);
+}
+
+static struct irq_domain_ops imx_gpcv2_domain_ops = {
+ .xlate = imx_gpcv2_domain_xlate,
+ .alloc = imx_gpcv2_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+};
+
+static int __init imx_gpcv2_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *parent_domain, *domain;
+ int i, val;
+
+ if (!parent) {
+ pr_err("%s: no parent, giving up\n", node->full_name);
+ return -ENODEV;
+ }
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ pr_err("%s: unable to obtain parent domain\n", node->full_name);
+ return -ENXIO;
+ }
+
+ gpc_base = of_iomap(node, 0);
+ if (WARN_ON(!gpc_base))
+ return -ENOMEM;
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
+ node, &imx_gpcv2_domain_ops,
+ NULL);
+ if (!domain) {
+ iounmap(gpc_base);
+ return -ENOMEM;
+ }
+
+ /* Initially mask all interrupts */
+ for (i = 0; i < IMR_NUM; i++) {
+ writel_relaxed(~0, gpc_base + GPC_IMR1_CORE0 + i * 4);
+ writel_relaxed(~0, gpc_base + GPC_IMR1_CORE1 + i * 4);
+ }
+ /*
+ * Due to hardware design requirement, need to make sure GPR
+ * interrupt(#32) is unmasked during RUN mode to avoid entering
+ * DSM by mistake.
+ */
+ writel_relaxed(~0x1, gpc_base + GPC_IMR1_CORE0);
+
+ /* Read supported wakeup source in M/F domain */
+ if (cpu_is_imx7d()) {
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 0,
+ &gpcv2_mf_irqs[0]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 1,
+ &gpcv2_mf_irqs[1]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 2,
+ &gpcv2_mf_irqs[2]);
+ of_property_read_u32_index(node, "fsl,mf-mix-wakeup-irq", 3,
+ &gpcv2_mf_irqs[3]);
+ if (!(gpcv2_mf_irqs[0] | gpcv2_mf_irqs[1] |
+ gpcv2_mf_irqs[2] | gpcv2_mf_irqs[3]))
+ pr_info("No wakeup source in Mega/Fast domain found!\n");
+ }
+
+ /* only external IRQs to wake up LPM and core 0/1 */
+ val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC);
+ val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP;
+ writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC);
+ /* mask m4 dsm trigger if M4 NOT enabled */
+ if (!imx_src_is_m4_enabled())
+ writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
+ BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
+ /* set mega/fast mix in A7 domain */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING);
+ /* set SCU timing */
+ writel_relaxed((0x59 << 10) | 0x5B | (0x2 << 20),
+ gpc_base + GPC_PGC_SCU_TIMING);
+
+ /* set C0/C1 power up timming per design requirement */
+ val = readl_relaxed(gpc_base + GPC_PGC_C0_PUPSCR);
+ val &= ~BM_GPC_PGC_CORE_PUPSCR;
+ val |= (0x1A << 7);
+ writel_relaxed(val, gpc_base + GPC_PGC_C0_PUPSCR);
+
+ val = readl_relaxed(gpc_base + GPC_PGC_C1_PUPSCR);
+ val &= ~BM_GPC_PGC_CORE_PUPSCR;
+ val |= (0x1A << 7);
+ writel_relaxed(val, gpc_base + GPC_PGC_C1_PUPSCR);
+
+ writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK |
+ BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK,
+ gpc_base + GPC_PGC_ACK_SEL_A7);
+
+ val = readl_relaxed(gpc_base + GPC_SLPCR);
+ val &= ~(BM_SLPCR_EN_DSM);
+ if (!imx_src_is_m4_enabled())
+ val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
+ BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
+ val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE;
+ writel_relaxed(val, gpc_base + GPC_SLPCR);
+
+ if (imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
+ /* disable memory low power mode */
+ val = readl_relaxed(gpc_base + GPC_MLPCR);
+ val |= BM_GPC_MLPCR_MEMLP_CTL_DIS;
+ writel_relaxed(val, gpc_base + GPC_MLPCR);
+ }
+
+ /* disable RBC */
+ imx_gpcv2_enable_rbc(false);
+
+ /*
+ * Clear the OF_POPULATED flag set in of_irq_init so that
+ * later the GPC power domain driver will not be skipped.
+ */
+ of_node_clear_flag(node, OF_POPULATED);
+
+ return 0;
+}
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, imx_gpcv2, "fsl,imx7d-gpc", imx_gpcv2_init);
+
+void __init imx_gpcv2_check_dt(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
+ if (WARN_ON(!np))
+ return;
+
+ if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
+ pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
+
+ /* map GPC, so that at least CPUidle and WARs keep working */
+ gpc_base = of_iomap(np, 0);
+ }
+}
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index 92c5a9c9f94b..eb05e8592729 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -81,13 +81,16 @@
* CCM 0x020c4000+0x004000 -> 0xf42c4000+0x004000
* ANATOP 0x020c8000+0x004000 -> 0xf42c8000+0x004000
* UART4 0x021f0000+0x004000 -> 0xf42f0000+0x004000
+ * mx7d:
+ * CCM 0x30380000+0x010000 -> 0xf5380000+0x010000
+ * ANATOP 0x30360000+0x010000 -> 0xf5360000+0x010000
+ * UART1 0x30860000+0x010000 -> 0xf5860000+0x010000
*/
#define IMX_IO_P2V(x) ( \
- (((x) & 0x80000000) >> 7) | \
(0xf4000000 + \
- (((x) & 0x50000000) >> 6) + \
- (((x) & 0x0b000000) >> 4) + \
- (((x) & 0x000fffff))))
+ (((x) & 0x50000000) >> 4) + \
+ (((x) & 0x0a000000) >> 4) + \
+ (((x) & 0x00ffffff))))
#define IMX_IO_ADDRESS(x) IOMEM(IMX_IO_P2V(x))
@@ -99,6 +102,9 @@
#include "mx2x.h"
#include "mx21.h"
#include "mx27.h"
+#include "mx6.h"
+#include "mx7.h"
+#include "mx7ulp.h"
#define imx_map_entry(soc, name, _type) { \
.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR), \
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index 766dbdb2ae27..c19cfc3166ae 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -21,6 +21,17 @@ diag_reg_offset:
ENTRY(v7_secondary_startup)
ARM_BE8(setend be) @ go BE8 if entered LE
+ mrc p15, 0, r0, c0, c0, 0
+ ldr r1, =0xf00
+ orr r1, r1, #0xff
+ mov r0, r0, lsr #4
+ and r0, r0, r1
+ /* 0xc07 is cortex A7's ID */
+ ldr r1, =0xc00
+ orr r1, r1, #0x7
+ cmp r0, r1
+ beq secondary_startup
+
set_diag_reg
b secondary_startup
ENDPROC(v7_secondary_startup)
diff --git a/arch/arm/mach-imx/imx6sl_low_power_idle.S b/arch/arm/mach-imx/imx6sl_low_power_idle.S
new file mode 100644
index 000000000000..978f8d1cc234
--- /dev/null
+++ b/arch/arm/mach-imx/imx6sl_low_power_idle.S
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 teh 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/linkage.h>
+
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x0
+#define PM_INFO_TTBR_OFFSET 0x4
+#define PM_INFO_MMDC_V_OFFSET 0x8
+#define PM_INFO_IOMUXC_V_OFFSET 0xc
+#define PM_INFO_CCM_V_OFFSET 0x10
+#define PM_INFO_L2_V_OFFSET 0x14
+#define PM_INFO_ANATOP_V_OFFSET 0x18
+#define PM_INFO_IO_NUM_OFFSET 0x1c
+#define PM_INFO_IO_VAL_OFFSET 0x20
+
+#define MX6Q_MMDC_MAPSR 0x404
+#define MX6Q_MMDC_MPDGCTRL0 0x83c
+
+.global mx6sl_lpm_wfi_start
+.global mx6sl_lpm_wfi_end
+
+ .macro pll_do_wait_lock
+1:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 1b
+
+ .endm
+
+ .macro ccm_do_wait
+2:
+ ldr r7, [r10, #0x48]
+ cmp r7, #0x0
+ bne 2b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ /*
+ * if in audio_bus_freq_mode, skip to
+ * audio_mode low power setting.
+ */
+ cmp r1, #0x1
+ beq audio_mode
+ /*
+ * Now set DDR rate to 1MHz.
+ * DDR is from bypassed PLL2 on periph2_clk2 path.
+ * Set the periph2_clk2_podf to divide by 8.
+ */
+ ldr r6, [r10, #0x14]
+ orr r6, r6, #0x07
+ str r6, [r10, #0x14]
+
+ /* Now set MMDC PODF to divide by 3. */
+ ldr r6, [r10, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, #0x10
+ str r6, [r10, #0x14]
+
+ ccm_do_wait
+
+ /* Set the AHB to 3MHz. AXI to 3MHz. */
+ ldr r6, [r10, #0x14]
+ /*r12 stores the origin AHB podf value */
+ mov r12, r6
+ orr r6, r6, #0x1c00
+ orr r6, r6, #0x70000
+ str r6, [r10, #0x14]
+
+ ccm_do_wait
+
+ /* Now set ARM to 24MHz.
+ * Move ARM to be sourced from step_clk
+ * after setting step_clk to 24MHz.
+ */
+ ldr r6, [r10, #0x0c]
+ bic r6, r6, #0x100
+ str r6, [r10, #0xc]
+ /*Now pll1_sw_clk to step_clk */
+ ldr r6, [r10, #0x0c]
+ orr r6, r6, #0x4
+ str r6, [r10, #0x0c]
+
+ /* Bypass PLL1 and power it down */
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ ldr r6, =(1 << 16)
+ orr r6, r6, #0x1000
+ str r6, [r10, #0x04]
+
+ /*
+ * Set the ARM PODF to divide by 8.
+ * IPG is at 1.5MHz here, we need ARM to
+ * run at the 12:5 ratio (WAIT mode issue).
+ */
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ ldr r11, [r10, #0x10]
+ ldr r6, =0x07
+ str r6, [r10, #0x10]
+
+ ccm_do_wait
+
+ b ccm_idle_done
+
+audio_mode:
+ /*
+ * MMDC is sourced from pll2_200M.
+ * Set the mmdc_podf to div by 8
+ */
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ ldr r6, [r10, #0x14]
+ orr r6, r6, #0x38
+ str r6, [r10, #0x14]
+
+ ccm_do_wait
+
+ /*
+ * ARM is sourced from pll2_pfd2_400M here.
+ * switch ARM to bypassed PLL1
+ */
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ ldr r6, [r10, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r10, #0xc]
+
+ /*
+ * set the arm_podf to divide by 3
+ * as IPG is at 4MHz, we cannot run
+ * arm clk above 9.6MHz when system
+ * enter WAIT mode
+ */
+ ldr r11, [r10, #0x10]
+ ldr r6, =0x2
+ str r6, [r10, #0x10]
+
+ ccm_do_wait
+
+ccm_idle_done:
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ /*
+ * If in audio_bus_freq_mode, skip to
+ * audio_mode ccm restore.
+ */
+ cmp r1, #0x1
+ beq audio_ccm_restore
+
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ /* Power up PLL1 and un-bypass it. */
+ ldr r6, =(1 << 12)
+ str r6, [r10, #0x08]
+
+ /* Wait for PLL1 to relock */
+ ldr r8, =0x0
+ pll_do_wait_lock
+
+ ldr r6, =(1 << 16)
+ str r6, [r10, #0x08]
+
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ /* Set PLL1_sw_clk back to PLL1 */
+ ldr r6, [r10, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r10, #0x0c]
+
+ /* Restore AHB/AXI back */
+ str r12, [r10, #0x14]
+
+ ccm_do_wait
+
+ /* restore mmdc back to 24MHz*/
+ ldr r6, [r10, #0x14]
+ bic r6, r6, #0x3f
+ str r6, [r10, #0x14]
+
+ ccm_do_wait
+ b ccm_exit_done
+
+audio_ccm_restore:
+ /* move arm clk back to pll2_pfd2_400M */
+ ldr r6, [r10, #0xc]
+ orr r6, r6, #0x4
+ str r6, [r10, #0xc]
+
+ /* restore mmdc podf */
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ ldr r6, [r10, #0x14]
+ bic r6, r6, #0x38
+ orr r6, #0x8
+ str r6, [r10, #0x14]
+
+ ccm_do_wait
+
+ccm_exit_done:
+
+ .endm
+
+ .macro check_pll_state
+
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ /*
+ * Check whether any PLL is enabled, as only when
+ * there is no PLLs enabled, 2p5 can be off and
+ * only enable the weak one. PLL1 will be powered
+ * down late, so no need to check PLL1 state.
+ */
+
+ /* sys PLL2 */
+ ldr r6, [r10, #0x30]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ /* usb PLL3 */
+ ldr r6, [r10, #0x10]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ /* audio PLL4 */
+ ldr r6, [r10, #0x70]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ /* video PLL5 */
+ ldr r6, [r10, #0xa0]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ /* enet PLL6 */
+ ldr r6, [r10, #0xe0]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ /* usb host PLL7 */
+ ldr r6, [r10, #0x20]
+ ands r6, r6, #(1 << 31)
+ bne 1f
+
+ ldr r4, =0x1
+ b check_done
+1:
+ ldr r4, =0x0
+
+check_done:
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ cmp r4, #0x0
+ beq anatop_enter_done
+
+ /* Disable 1p1 brown out. */
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ ldr r6, [r10, #0x110]
+ bic r6, r6, #0x2
+ str r6, [r10, #0x110]
+ /*
+ * Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r6, [r10, #0x150]
+ orr r6, r6, #0xc000
+ str r6, [r10, #0x150]
+
+ /*
+ * if the usb VBUS wakeup is enabled, skip
+ * disable main 2p5.
+ */
+ cmp r2, #0x1
+ beq anatop_enter_done
+
+ /* Enable the week 2p5 */
+ ldr r6, [r10, #0x130]
+ orr r6, r6, #0x40000
+ str r6, [r10, #0x130]
+
+ /* Disable main 2p5. */
+ ldr r6, [r10, #0x130]
+ bic r6, r6, #0x1
+ str r6, [r10, #0x130]
+
+ /*
+ * Cannot diable regular bandgap
+ * in LDO-enable mode. The bandgap
+ * is required for ARM-LDO to regulate
+ * the voltage.
+ */
+ ldr r6, [r10, #0x140]
+ and r6, r6, #0x1f
+ cmp r6, #0x1f
+ bne anatop_enter_done
+
+ /* Enable low power bandgap */
+ ldr r6, [r10, #0x260]
+ orr r6, r6, #0x20
+ str r6, [r10, #0x260]
+
+ /*
+ * Turn off the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r10, #0x260]
+ orr r6, r6, #0x80
+ str r6, [r10, #0x260]
+
+ /*
+ * Clear the REFTTOP+SELFBIASOFF,
+ * self_bais circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r6, [r10, #0x150]
+ bic r6, r6, #0x8
+ str r6, [r10, #0x150]
+
+ /* Power down the regular bandgap */
+ ldr r6, [r10, #0x150]
+ orr r6, r6, #0x1
+ str r6, [r10, #0x150]
+anatop_enter_done:
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
+ cmp r4, #0x0
+ beq skip_anatop_restore
+
+ cmp r2, #0x1
+ beq ldo2p5_not_disabled
+ /*
+ * Regular bandgap will not be disabled
+ * in LDO-enabled mode as it is required
+ * for ARM-LDO to reguulate the voltage.
+ */
+ ldr r6, [r10, #0x140]
+ and r6, r6, #0x1f
+ cmp r6, #0x1f
+ bne skip_bandgap_restore
+
+ /* Power up the regular bandgap */
+ ldr r6, [r10, #0x150]
+ bic r6, r6, #0x1
+ str r6, [r10, #0x150]
+
+ /* wait for bandgap stable */
+3:
+ ldr r6, [r10, #0x150]
+ and r6, r6, #0x80
+ cmp r6, #0x80
+ bne 3b
+
+ /* now disable bandgap self-bias circuit */
+ ldr r6, [r10, #0x150]
+ orr r6, r6, #0x8
+ str r6, [r10, #0x150]
+
+ /* Turn on the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r10, #0x260]
+ bic r6, r6, #0x80
+ str r6, [r10, #0x260]
+
+ /* Disable the low power bandgap */
+ ldr r6, [r10, #0x260]
+ bic r6, r6, #0x20
+ str r6, [r10, #0x260]
+
+skip_bandgap_restore:
+ /* Enable main 2p5. */
+ ldr r6, [r10, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r10, #0x130]
+
+ /* Ensure the 2p5 is up */
+5:
+ ldr r6, [r10, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne 5b
+
+ /* Disable the weak 2p5 */
+ ldr r6, [r10, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r10, #0x130]
+
+ldo2p5_not_disabled:
+ /*
+ * Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r10, #0x150]
+ bic r6, r6, #0xc000
+ str r6, [r10, #0x150]
+
+ /* Enable 1p1 brown out, */
+ ldr r6, [r10, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r10, #0x110]
+
+skip_anatop_restore:
+
+ .endm
+
+ .macro disable_l1_dcache
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+ dsb
+ isb
+
+ .endm
+
+ .macro mmdc_enter_dvfs_mode
+
+ /* disable automatic power saving. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* disable power down timer */
+ ldr r7, [r10, #0x04]
+ bic r7, r7, #0xff00
+ str r7, [r10, #0x04]
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+poll_dvfs_set:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq poll_dvfs_set
+
+ /* set SBS step-by step mode */
+ ldr r7, [r10, #0x410]
+ orr r7, r7, #0x100
+ str r7, [r10, #0x410]
+
+ .endm
+
+ .macro resume_mmdc
+ /* restore MMDC IO */
+ ldr r10, [r0, #PM_INFO_IOMUXC_V_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_IO_VAL_OFFSET
+ add r7, r7, r0
+6:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 6b
+
+ /*
+ * Need to reset the FIFO to avoid MMDC lockup
+ * caused because of floating/changing the
+ * configuration of many DDR IO pads.
+ */
+ ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+7:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 7b
+
+ /* reset FIFO a second time */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+8:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 <<31)
+ bne 8b
+
+ ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
+ /* Let DDR out of self-refresh */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+9:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 9b
+
+ /* enable power down timer */
+ ldr r7, [r10, #0x04]
+ orr r7, r7, #0x5500
+ str r7, [r10, #0x04]
+
+ /* enable DDR auto power saving */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* Clear SBS - unblock DDR accesses */
+ ldr r7, [r10, #0x410]
+ bic r7, r7, #0x100
+ str r7, [r10, #0x410]
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * we need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to the IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is transslated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Disable Branch Prediction, Z bit in SCTLR */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+
+ /* store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+ /* Read TTBCR and set PD0=1, N=1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* Flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N=0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ /* Flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0 ,r6, c1, c0, 0
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+ /* Restore ttbr */
+ ldr r7, [r0, #PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+/*
+ * imx6sl_low_power_wfi code
+ * r0: wfi code base address
+ * r1: audio_bus_freq mode stat
+ * r2: vbus_ldo status
+ * r4: used for store the PLLs state
+ * r11: used for saving the ARM_PODF origin value
+ * r12: used for saving AHB_PODF origin value
+ */
+ .align 3
+ENTRY(imx6sl_low_power_idle)
+
+mx6sl_lpm_wfi_start:
+ push {r4-r12}
+
+ tlb_set_to_ocram
+ disable_l1_dcache
+
+#ifdef CONFIG_CACHE_L2X0
+ /* sync L2 */
+ ldr r10, [r0, #PM_INFO_L2_V_OFFSET]
+ /* Wait for background operations to complete. */
+wait_for_l2_idle:
+ ldr r6, [r10, #0x730]
+ cmp r6, #0x0
+ bne wait_for_l2_idle
+
+ mov r6, #0x0
+ str r6, [r10, #0x730]
+ /* disable L2 */
+ str r6, [r10, #0x100]
+
+ dsb
+ isb
+#endif
+
+ /* make sure MMDC in self-refresh */
+ ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
+ mmdc_enter_dvfs_mode
+ /* save DDR IO settings and set to LPM mode*/
+ ldr r10, [r0, #PM_INFO_IOMUXC_V_OFFSET]
+ ldr r6, =0x0
+ ldr r7, [r0, #PM_INFO_IO_NUM_OFFSET]
+ ldr r8, =PM_INFO_IO_VAL_OFFSET
+ add r8, r8, r0
+
+ /* imx6sl's last 3 IOs need special setting */
+ sub r7, r7, #0x3
+save_and_set_mmdc_io_lpm:
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ subs r7, r7, #0x1
+ bne save_and_set_mmdc_io_lpm
+ ldr r6, =0x1000
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r5, [r8], #0x4
+ str r6, [r10, r9]
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ ldr r6, =0x80000
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+
+
+ /* check the PLLs lock state */
+ check_pll_state
+
+ ccm_enter_idle
+ /* if in audio low power mode, no
+ * need to do anatop setting.
+ */
+ cmp r1, #0x1
+ beq do_wfi
+ anatop_enter_idle
+do_wfi:
+ wfi
+ /*
+ * Add these nops so that the
+ * prefetcher will not try to get
+ * any instrutions from DDR.
+ * The prefetch depth is about 23
+ * on A9, so adding 25 nops.
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /*
+ * restore the ARM PODF first to speed
+ * up the restore procedure
+ */
+ ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
+ /* Restore arm_clk_podf */
+ str r11, [r10, #0x10]
+ ccm_do_wait
+
+ /*
+ * if in audio low power mode, skip
+ * restore the anatop setting.
+ */
+ cmp r1, #0x1
+ beq skip_analog_restore
+ anatop_exit_idle
+
+skip_analog_restore:
+ ccm_exit_idle
+ resume_mmdc
+
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r10, [r0, #PM_INFO_L2_V_OFFSET]
+ mov r7, #0x1
+ /* enable L2 */
+ str r7, [r10, #0x100]
+#endif
+ tlb_back_to_ddr
+
+ /* Restore register */
+ pop {r4 - r12}
+ mov pc, lr
+
+ /*
+ * Add ltorg here to ensure that all
+ * literals are stored here and are
+ * within the text space.
+ */
+ .ltorg
+mx6sl_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/imx6sll_low_power_idle.S b/arch/arm/mach-imx/imx6sll_low_power_idle.S
new file mode 100644
index 000000000000..a7e206ecbb42
--- /dev/null
+++ b/arch/arm/mach-imx/imx6sll_low_power_idle.S
@@ -0,0 +1,780 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+
+#define PM_INFO_PBASE_OFFSET 0x0
+#define PM_INFO_RESUME_ADDR_OFFSET 0x4
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x8
+#define PM_INFO_PM_INFO_TTBR_OFFSET 0xc
+#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
+#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x18
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x1c
+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x20
+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x24
+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x28
+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x2c
+#define PM_INFO_MX6Q_ANATOP_P_OFFSET 0x30
+#define PM_INFO_MX6Q_ANATOP_V_OFFSET 0x34
+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x38
+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x3c
+#define PM_INFO_MX6Q_L2_P_OFFSET 0x40
+#define PM_INFO_MX6Q_L2_V_OFFSET 0x44
+#define PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET 0x48
+
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x4c
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x50
+
+#define MX6Q_MMDC_MAPSR 0x404
+#define MX6Q_MMDC_MPDGCTRL0 0x83c
+#define MX6Q_SRC_GPR1 0x20
+#define MX6Q_SRC_GPR2 0x24
+#define MX6Q_GPC_IMR1 0x08
+#define MX6Q_GPC_IMR2 0x0c
+#define MX6Q_GPC_IMR3 0x10
+#define MX6Q_GPC_IMR4 0x14
+#define MX6Q_CCM_CCR 0x0
+
+.globl mx6sll_lpm_wfi_start
+.globl mx6sll_lpm_wfi_end
+
+ .macro pll_do_wait_lock
+1:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 1b
+
+ .endm
+
+ .macro ccm_do_wait
+2:
+ ldr r7, [r10, #0x48]
+ cmp r7, #0x0
+ bne 2b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set ahb to 3MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ /* set perclk to 6MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ orr r7, r7, #0x3
+ str r7, [r10, #0x1c]
+
+ /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x2
+ orr r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * disable pll2, suppose when system enter low
+ * power idle mode, only 396MHz pfd needs pll2,
+ * now we switch arm clock to OSC, we can disable
+ * pll2 now, gate pll2_pfd2 first.
+ */
+ ldr r7, [r10, #0x100]
+ orr r7, #0x800000
+ str r7, [r10, #0x100]
+
+ ldr r7, [r10, #0x30]
+ orr r7, r7, #0x1000
+ bic r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* enable pll2 and pll2_pfd2 */
+ ldr r7, [r10, #0x30]
+ bic r7, r7, #0x1000
+ orr r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ ldr r8, =0x30
+ pll_do_wait_lock
+
+ ldr r7, [r10, #0x100]
+ bic r7, #0x800000
+ str r7, [r10, #0x100]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
+
+ /* set perclk back to 24MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ str r7, [r10, #0x1c]
+
+ /* set mmdc back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x7
+ bic r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ /* set ahb div back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * check whether any PLL is enabled, as only when
+ * there is no PLLs enabled, 2P5 and 1P1 can be
+ * off and only enable weak ones.
+ */
+
+ /* arm pll1 */
+ ldr r7, [r10, #0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* sys pll2 */
+ ldr r7, [r10, #0x30]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb pll3 */
+ ldr r7, [r10, #0x10]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* audio pll4 */
+ ldr r7, [r10, #0x70]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* vidio pll5 */
+ ldr r7, [r10, #0xa0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enet pll6 */
+ ldr r7, [r10, #0xe0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb host pll7 */
+ ldr r7, [r10, #0x20]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enable weak 2P5 and turn off regular 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x130]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* enable weak 1p1 and turn off regular 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x110]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x110]
+
+ /* low power band gap enable */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x20
+ str r7, [r10, #0x270]
+
+ /* turn off the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /*
+ * clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn off regular bandgap */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x150]
+
+10:
+ /* switch to RC-OSC */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x40000000
+ str r7, [r10, #0x150]
+
+ /* lower OSC current by 37.5% */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* disconnect vdd_high_in and vdd_snvs_in */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1000
+ str r7, [r10, #0x150]
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* increase OSC current to normal */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* turn on XTAL-OSC and detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x40000000
+ orr r7, r7, #0x10000
+ str r7, [r10, #0x150]
+
+ /* wait for XTAL stable */
+14:
+ ldr r7, [r10, #0x150]
+ ands r7, r7, #0x8000
+ beq 14b
+
+ /* switch to XTAL-OSC */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x10000
+ str r7, [r10, #0x150]
+15:
+ /* check whether we need to enable 2P5/1P1 */
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x40000
+ beq 11f
+
+ /* turn on regular bandgap and wait for stable */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x150]
+13:
+ ldr r7, [r10, #0x150]
+ ands r7, #0x80
+ beq 13b
+
+ /*
+ * set the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn on the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /* low power band gap disable */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x20
+ str r7, [r10, #0x270]
+12:
+ /* enable regular 2P5 and turn off weak 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* Ensure the 2P5 is up. */
+3:
+ ldr r7, [r10, #0x130]
+ ands r7, r7, #0x20000
+ beq 3b
+ ldr r7, [r10, #0x130]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x130]
+
+ /* enable regular 1p1 and turn off weak 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x110]
+4:
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x20000
+ beq 4b
+ ldr r7, [r10, #0x110]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x110]
+11:
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro mmdc_enter_dvfs_mode
+
+ /* disable automatic power savings. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* make the DDR explicitly enter self-refresh. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+5:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq 5b
+
+ .endm
+
+ .macro resume_mmdc
+
+ /* restore MMDC IO */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+6:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 6b
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
+
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+7:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 7b
+
+ /* reset FIFO a second time */
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+8:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 8b
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+9:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 9b
+
+ /* enable DDR auto power saving */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Restore the TTBCR */
+
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* restore ttbr */
+ ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+/* imx6sx_low_power_idle */
+
+ .align 3
+ENTRY(imx6sll_low_power_idle)
+mx6sll_lpm_wfi_start:
+ push {r4 - r10}
+
+ /* get necessary info from pm_info */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r5, =imx6sll_low_power_idle
+ ldr r6, =wakeup
+ sub r6, r6, r5
+ add r8, r1, r2
+ add r3, r8, r6
+
+ /* store physical resume addr and pm_info address. */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
+ str r3, [r10, #0x20]
+ str r1, [r10, #0x24]
+
+ /* save disagnostic register */
+ mrc p15, 0, r7, c15, c0, 1
+ str r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
+
+ /* set ARM power to be gated */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r10, #0x2a0]
+
+ disable_l1_dcache
+
+#ifdef CONFIG_CACHE_L2X0
+ /* sync L2 */
+ ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r7, [r10, #0x730]
+ cmp r7, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r7, #0x0
+ str r7, [r10, #0x730]
+ /* disable L2 */
+ str r7, [r10, #0x100]
+
+ dsb
+ isb
+#endif
+
+ tlb_set_to_ocram
+
+ /* make sure MMDC in self-refresh */
+ ldr r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ mmdc_enter_dvfs_mode
+
+ /* save DDR IO settings */
+ ldr r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldr r6, =0x0
+ ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r8, r8, r0
+save_and_set_mmdc_io_lpm:
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ subs r7, r7, #0x1
+ bne save_and_set_mmdc_io_lpm
+
+ mov r5, #0x0
+ ccm_enter_idle
+ anatop_enter_idle
+
+ /*
+ * mask all GPC interrupts before
+ * enabling the RBC counters to
+ * avoid the counter starting too
+ * early if an interupt is already
+ * pending.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r4, [r10, #MX6Q_GPC_IMR1]
+ ldr r5, [r10, #MX6Q_GPC_IMR2]
+ ldr r6, [r10, #MX6Q_GPC_IMR3]
+ ldr r7, [r10, #MX6Q_GPC_IMR4]
+
+ ldr r3, =0xffffffff
+ str r3, [r10, #MX6Q_GPC_IMR1]
+ str r3, [r10, #MX6Q_GPC_IMR2]
+ str r3, [r10, #MX6Q_GPC_IMR3]
+ str r3, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 4 (120us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~130uS.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ bic r3, r3, #(0x3f << 21)
+ orr r3, r3, #(0x4 << 21)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* enable the counter. */
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ orr r3, r3, #(0x1 << 27)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* unmask all the GPC interrupts. */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ str r4, [r10, #MX6Q_GPC_IMR1]
+ str r5, [r10, #MX6Q_GPC_IMR2]
+ str r6, [r10, #MX6Q_GPC_IMR3]
+ str r7, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 24MHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r4, =50
+rbc_loop:
+ subs r4, r4, #0x1
+ bne rbc_loop
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mov r5, #0x0
+ anatop_exit_idle
+ ccm_exit_idle
+ resume_mmdc
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+ mov r7, #0x1
+ /* enable L2 */
+ str r7, [r10, #0x100]
+#endif
+
+ tlb_back_to_ddr
+
+ /* Restore registers */
+ pop {r4 - r10}
+ mov pc, lr
+
+wakeup:
+
+ /* invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0
+ isb
+ /* restore disagnostic register */
+ ldr r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
+ mcr p15, 0, r7, c15, c0, 1
+
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ /* clear core0's entry and parameter */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
+ mov r7, #0x0
+ str r7, [r10, #MX6Q_SRC_GPR1]
+ str r7, [r10, #MX6Q_SRC_GPR2]
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ mov r5, #0x1
+ anatop_exit_idle
+ ccm_exit_idle
+ resume_mmdc
+
+ /* Restore registers */
+ mov pc, lr
+ .ltorg
+mx6sll_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/imx6sx_low_power_idle.S b/arch/arm/mach-imx/imx6sx_low_power_idle.S
new file mode 100644
index 000000000000..7ddda1cd1a8f
--- /dev/null
+++ b/arch/arm/mach-imx/imx6sx_low_power_idle.S
@@ -0,0 +1,887 @@
+/*
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+
+#define PM_INFO_PBASE_OFFSET 0x0
+#define PM_INFO_RESUME_ADDR_OFFSET 0x4
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x8
+#define PM_INFO_PM_INFO_TTBR_OFFSET 0xc
+#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
+#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x18
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x1c
+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x20
+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x24
+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x28
+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x2c
+#define PM_INFO_MX6Q_L2_P_OFFSET 0x30
+#define PM_INFO_MX6Q_L2_V_OFFSET 0x34
+#define PM_INFO_MX6Q_ANATOP_P_OFFSET 0x38
+#define PM_INFO_MX6Q_ANATOP_V_OFFSET 0x3c
+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x40
+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x44
+#define PM_INFO_MX6Q_SEMA4_P_OFFSET 0x48
+#define PM_INFO_MX6Q_SEMA4_V_OFFSET 0x4c
+#define PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET 0x50
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x54
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x58
+
+#define MX6Q_MMDC_MAPSR 0x404
+#define MX6Q_MMDC_MPDGCTRL0 0x83c
+#define MX6Q_SRC_GPR1 0x20
+#define MX6Q_SRC_GPR2 0x24
+#define MX6Q_GPC_IMR1 0x08
+#define MX6Q_GPC_IMR2 0x0c
+#define MX6Q_GPC_IMR3 0x10
+#define MX6Q_GPC_IMR4 0x14
+#define MX6Q_CCM_CCR 0x0
+
+.globl mx6sx_lpm_wfi_start
+.globl mx6sx_lpm_wfi_end
+
+ .macro pll_do_wait_lock
+1:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 1b
+
+ .endm
+
+ .macro ccm_do_wait
+2:
+ ldr r7, [r10, #0x48]
+ cmp r7, #0x0
+ bne 2b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set ahb to 3MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ /* set perclk to 6MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ orr r7, r7, #0x3
+ str r7, [r10, #0x1c]
+
+ /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x2
+ orr r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set pll1_sw to from pll1 main */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ /* set step from osc */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x100
+ str r7, [r10, #0xc]
+
+ /* set pll1_sw to from step */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /* Disable PLL1 bypass output */
+ ldr r7, [r10]
+ bic r7, r7, #0x12000
+ str r7, [r10]
+
+ /*
+ * disable pll2, suppose when system enter low
+ * power idle mode, only 396MHz pfd needs pll2,
+ * now we switch arm clock to OSC, we can disable
+ * pll2 now, gate pll2_pfd2 first.
+ */
+ ldr r7, [r10, #0x100]
+ orr r7, #0x800000
+ str r7, [r10, #0x100]
+
+ ldr r7, [r10, #0x30]
+ orr r7, r7, #0x1000
+ bic r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* enable pll2 and pll2_pfd2 */
+ ldr r7, [r10, #0x30]
+ bic r7, r7, #0x1000
+ orr r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ ldr r8, =0x30
+ pll_do_wait_lock
+
+ ldr r7, [r10, #0x100]
+ bic r7, #0x800000
+ str r7, [r10, #0x100]
+
+ /* enable PLL1 bypass output */
+ ldr r7, [r10]
+ orr r7, r7, #0x12000
+ str r7, [r10]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
+
+ /* set perclk back to 24MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ str r7, [r10, #0x1c]
+
+ /* set mmdc back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x7
+ bic r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ /* set ahb div back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ /* set pll1_sw to from pll1 main */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ /* set step from pll2_pfd2 */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x100
+ str r7, [r10, #0xc]
+
+ /* set pll1_sw to from step */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * check whether any PLL is enabled, as only when
+ * there is no PLLs enabled, 2P5 and 1P1 can be
+ * off and only enable weak ones.
+ */
+
+ /* arm pll1 */
+ ldr r7, [r10, #0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* sys pll2 */
+ ldr r7, [r10, #0x30]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb pll3 */
+ ldr r7, [r10, #0x10]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* audio pll4 */
+ ldr r7, [r10, #0x70]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* vidio pll5 */
+ ldr r7, [r10, #0xa0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enet pll6 */
+ ldr r7, [r10, #0xe0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb host pll7 */
+ ldr r7, [r10, #0x20]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enable weak 2P5 and turn off regular 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x130]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* enable weak 1p1 and turn off regular 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x110]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x110]
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 10f
+
+ /* low power band gap enable */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x20
+ str r7, [r10, #0x270]
+
+ /* turn off the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /*
+ * clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn off regular bandgap */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x150]
+
+ /* only switch to RC-OSC clk after TO1.2 */
+ ldr r7, [r10, #0x260]
+ and r7, r7, #0x3
+ cmp r7, #0x2
+ blt 10f
+
+ /* switch to RC-OSC */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x40000000
+ str r7, [r10, #0x150]
+10:
+ /* lower OSC current by 37.5% */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* increase OSC current to normal */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* only switch to RC-OSC after TO1.2 */
+ ldr r7, [r10, #0x260]
+ and r7, r7, #0x3
+ cmp r7, #0x2
+ blt 15f
+
+ /* turn on XTAL-OSC and detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x40000000
+ orr r7, r7, #0x10000
+ str r7, [r10, #0x150]
+
+ /* wait for XTAL stable */
+14:
+ ldr r7, [r10, #0x150]
+ ands r7, r7, #0x8000
+ beq 14b
+
+ /* switch to XTAL-OSC */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x10000
+ str r7, [r10, #0x150]
+15:
+ /* check whether we need to enable 2P5/1P1 */
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x40000
+ beq 11f
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 12f
+
+ /* turn on regular bandgap and wait for stable */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x150]
+13:
+ ldr r7, [r10, #0x150]
+ ands r7, #0x80
+ beq 13b
+
+ /*
+ * set the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn on the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /* low power band gap disable */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x20
+ str r7, [r10, #0x270]
+12:
+ /* enable regular 2P5 and turn off weak 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* Ensure the 2P5 is up. */
+3:
+ ldr r7, [r10, #0x130]
+ ands r7, r7, #0x20000
+ beq 3b
+ ldr r7, [r10, #0x130]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x130]
+
+ /* enable regular 1p1 and turn off weak 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x110]
+4:
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x20000
+ beq 4b
+ ldr r7, [r10, #0x110]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x110]
+11:
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro mmdc_enter_dvfs_mode
+
+ /* disable automatic power savings. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* disable power down timer */
+ ldr r7, [r10, #0x4]
+ bic r7, r7, #0xff00
+ str r7, [r10, #0x4]
+
+ /* make the DDR explicitly enter self-refresh. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+5:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq 5b
+
+ .endm
+
+ .macro resume_mmdc
+
+ /* restore MMDC IO */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+6:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 6b
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
+
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+7:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 7b
+
+ /* reset FIFO a second time */
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+8:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 8b
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+9:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 9b
+
+ /* enable power down timer */
+ ldr r7, [r10, #0x4]
+ orr r7, r7, #0x5500
+ str r7, [r10, #0x4]
+
+ /* enable DDR auto power saving */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ .endm
+
+ .macro sema4_lock
+
+ /* lock share memory sema4 */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
+ ldrb r6, =0x1
+16:
+ ldrb r7, [r10, #0x6]
+ cmp r7, #0x0
+ bne 16b
+ strb r6, [r10, #0x6]
+
+ .endm
+
+ .macro sema4_unlock
+
+ /* unlock share memory sema4 */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
+ ldrb r6, =0x0
+ strb r6, [r10, #0x6]
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Restore the TTBCR */
+
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* restore ttbr */
+ ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+/* imx6sx_low_power_idle */
+
+ .align 3
+ENTRY(imx6sx_low_power_idle)
+mx6sx_lpm_wfi_start:
+ push {r4 - r10}
+
+ /* get necessary info from pm_info */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r5, =imx6sx_low_power_idle
+ ldr r6, =wakeup
+ sub r6, r6, r5
+ add r8, r1, r2
+ add r3, r8, r6
+
+ /* store physical resume addr and pm_info address. */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
+ str r3, [r10, #0x20]
+ str r1, [r10, #0x24]
+
+ /* save disagnostic register */
+ mrc p15, 0, r7, c15, c0, 1
+ str r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
+
+ /* set ARM power to be gated */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r10, #0x2a0]
+
+ disable_l1_dcache
+
+#ifdef CONFIG_CACHE_L2X0
+ /* sync L2 */
+ ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r7, [r10, #0x730]
+ cmp r7, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r7, #0x0
+ str r7, [r10, #0x730]
+ /* disable L2 */
+ str r7, [r10, #0x100]
+
+ dsb
+ isb
+#endif
+
+ tlb_set_to_ocram
+
+ /* make sure MMDC in self-refresh */
+ ldr r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ mmdc_enter_dvfs_mode
+
+ /* save DDR IO settings */
+ ldr r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldr r6, =0x0
+ ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r8, r8, r0
+save_and_set_mmdc_io_lpm:
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ subs r7, r7, #0x1
+ bne save_and_set_mmdc_io_lpm
+
+ mov r5, #0x0
+ sema4_lock
+ ccm_enter_idle
+ anatop_enter_idle
+ sema4_unlock
+
+ /*
+ * mask all GPC interrupts before
+ * enabling the RBC counters to
+ * avoid the counter starting too
+ * early if an interupt is already
+ * pending.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r4, [r10, #MX6Q_GPC_IMR1]
+ ldr r5, [r10, #MX6Q_GPC_IMR2]
+ ldr r6, [r10, #MX6Q_GPC_IMR3]
+ ldr r7, [r10, #MX6Q_GPC_IMR4]
+
+ ldr r3, =0xffffffff
+ str r3, [r10, #MX6Q_GPC_IMR1]
+ str r3, [r10, #MX6Q_GPC_IMR2]
+ str r3, [r10, #MX6Q_GPC_IMR3]
+ str r3, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 4 (120us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~130uS.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ bic r3, r3, #(0x3f << 21)
+ orr r3, r3, #(0x4 << 21)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* enable the counter. */
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ orr r3, r3, #(0x1 << 27)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* unmask all the GPC interrupts. */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ str r4, [r10, #MX6Q_GPC_IMR1]
+ str r5, [r10, #MX6Q_GPC_IMR2]
+ str r6, [r10, #MX6Q_GPC_IMR3]
+ str r7, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 24MHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r4, =50
+rbc_loop:
+ subs r4, r4, #0x1
+ bne rbc_loop
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mov r5, #0x0
+ sema4_lock
+ anatop_exit_idle
+ ccm_exit_idle
+ sema4_unlock
+ resume_mmdc
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+ mov r7, #0x1
+ /* enable L2 */
+ str r7, [r10, #0x100]
+#endif
+
+ tlb_back_to_ddr
+
+ /* Restore registers */
+ pop {r4 - r10}
+ mov pc, lr
+
+wakeup:
+
+ /* invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0
+ isb
+ /* restore disagnostic register */
+ ldr r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
+ mcr p15, 0, r7, c15, c0, 1
+
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ /* clear core0's entry and parameter */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
+ mov r7, #0x0
+ str r7, [r10, #MX6Q_SRC_GPR1]
+ str r7, [r10, #MX6Q_SRC_GPR2]
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ mov r5, #0x1
+ sema4_lock
+ anatop_exit_idle
+ ccm_exit_idle
+ sema4_unlock
+ resume_mmdc
+
+ /* Restore registers */
+ mov pc, lr
+ .ltorg
+mx6sx_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/imx6ul_low_power_idle.S b/arch/arm/mach-imx/imx6ul_low_power_idle.S
new file mode 100644
index 000000000000..26bb83da1a7d
--- /dev/null
+++ b/arch/arm/mach-imx/imx6ul_low_power_idle.S
@@ -0,0 +1,821 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+
+#define PM_INFO_PBASE_OFFSET 0x0
+#define PM_INFO_RESUME_ADDR_OFFSET 0x4
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x8
+#define PM_INFO_PM_INFO_TTBR_OFFSET 0xc
+#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
+#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x18
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x1c
+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x20
+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x24
+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x28
+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x2c
+#define PM_INFO_MX6Q_ANATOP_P_OFFSET 0x30
+#define PM_INFO_MX6Q_ANATOP_V_OFFSET 0x34
+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x38
+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x3c
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44
+
+#define MX6Q_MMDC_MAPSR 0x404
+#define MX6Q_MMDC_MPDGCTRL0 0x83c
+#define MX6Q_SRC_GPR1 0x20
+#define MX6Q_SRC_GPR2 0x24
+#define MX6Q_GPC_IMR1 0x08
+#define MX6Q_GPC_IMR2 0x0c
+#define MX6Q_GPC_IMR3 0x10
+#define MX6Q_GPC_IMR4 0x14
+#define MX6Q_CCM_CCR 0x0
+
+.globl mx6ul_lpm_wfi_start
+.globl mx6ul_lpm_wfi_end
+
+ .macro pll_do_wait_lock
+1:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 1b
+
+ .endm
+
+ .macro ccm_do_wait
+2:
+ ldr r7, [r10, #0x48]
+ cmp r7, #0x0
+ bne 2b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set ahb to 3MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ /* set perclk to 6MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ orr r7, r7, #0x3
+ str r7, [r10, #0x1c]
+
+ /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x2
+ orr r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /* bypass PLL1 output to OSC */
+ ldr r7, [r10]
+ orr r7, r7, #(0x1 << 16)
+ str r7, [r10]
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set pll1_sw to from pll1 main */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ /* set step from osc */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x100
+ str r7, [r10, #0xc]
+
+ /* set pll1_sw to from step */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /* Disable PLL1 bypass output */
+ ldr r7, [r10]
+ bic r7, r7, #0x12000
+ str r7, [r10]
+
+ /*
+ * disable pll2, suppose when system enter low
+ * power idle mode, only 396MHz pfd needs pll2,
+ * now we switch arm clock to OSC, we can disable
+ * pll2 now, gate pll2_pfd2 first.
+ */
+ ldr r7, [r10, #0x100]
+ orr r7, #0x800000
+ str r7, [r10, #0x100]
+
+ ldr r7, [r10, #0x30]
+ orr r7, r7, #0x1000
+ bic r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* enable pll2 and pll2_pfd2 */
+ ldr r7, [r10, #0x30]
+ bic r7, r7, #0x1000
+ orr r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ ldr r8, =0x30
+ pll_do_wait_lock
+
+ ldr r7, [r10, #0x100]
+ bic r7, #0x800000
+ str r7, [r10, #0x100]
+
+ /* enable PLL1 bypass output */
+ ldr r7, [r10]
+ orr r7, r7, #0x12000
+ str r7, [r10]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
+
+ /* set perclk back to 24MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ str r7, [r10, #0x1c]
+
+ /* set mmdc back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x7
+ bic r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ /* set ahb div back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ /* set pll1_sw to from pll1 main */
+ ldr r7, [r10, #0xc]
+ bic r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ /* set step from pll2_pfd2 */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x100
+ str r7, [r10, #0xc]
+
+ /* set pll1_sw to from step */
+ ldr r7, [r10, #0xc]
+ orr r7, r7, #0x4
+ str r7, [r10, #0xc]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* Unbypass PLL1 */
+ ldr r7, [r10]
+ bic r7, r7, #(0x1 << 16)
+ str r7, [r10]
+
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * check whether any PLL is enabled, as only when
+ * there is no PLLs enabled, 2P5 and 1P1 can be
+ * off and only enable weak ones.
+ */
+
+ /* arm pll1 */
+ ldr r7, [r10, #0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* sys pll2 */
+ ldr r7, [r10, #0x30]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb pll3 */
+ ldr r7, [r10, #0x10]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* audio pll4 */
+ ldr r7, [r10, #0x70]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* vidio pll5 */
+ ldr r7, [r10, #0xa0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enet pll6 */
+ ldr r7, [r10, #0xe0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb host pll7 */
+ ldr r7, [r10, #0x20]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enable weak 2P5 and turn off regular 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x130]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* enable weak 1p1 and turn off regular 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x110]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x110]
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 10f
+
+ /* low power band gap enable */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x20
+ str r7, [r10, #0x270]
+
+ /* turn off the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /*
+ * clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn off regular bandgap */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x150]
+
+ /* switch to RC-OSC */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x40000000
+ str r7, [r10, #0x150]
+10:
+ /* lower OSC current by 37.5% */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* disconnect vdd_high_in and vdd_snvs_in */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1000
+ str r7, [r10, #0x150]
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* increase OSC current to normal */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* turn on XTAL-OSC and detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x40000000
+ orr r7, r7, #0x10000
+ str r7, [r10, #0x150]
+
+ /* wait for XTAL stable */
+14:
+ ldr r7, [r10, #0x150]
+ ands r7, r7, #0x8000
+ beq 14b
+
+ /* switch to XTAL-OSC */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x10000
+ str r7, [r10, #0x150]
+15:
+ /* check whether we need to enable 2P5/1P1 */
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x40000
+ beq 11f
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 12f
+
+ /* turn on regular bandgap and wait for stable */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x150]
+13:
+ ldr r7, [r10, #0x150]
+ ands r7, #0x80
+ beq 13b
+
+ /*
+ * set the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn on the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /* low power band gap disable */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x20
+ str r7, [r10, #0x270]
+12:
+ /* enable regular 2P5 and turn off weak 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* Ensure the 2P5 is up. */
+3:
+ ldr r7, [r10, #0x130]
+ ands r7, r7, #0x20000
+ beq 3b
+ ldr r7, [r10, #0x130]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x130]
+
+ /* enable regular 1p1 and turn off weak 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x110]
+4:
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x20000
+ beq 4b
+ ldr r7, [r10, #0x110]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x110]
+11:
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro mmdc_enter_dvfs_mode
+
+ /* disable automatic power savings. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* disable power down timer */
+ ldr r7, [r10, #0x4]
+ bic r7, r7, #0xff00
+ str r7, [r10, #0x4]
+
+ /* make the DDR explicitly enter self-refresh. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+5:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq 5b
+
+ .endm
+
+ .macro resume_mmdc
+
+ /* restore MMDC IO */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+6:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 6b
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
+
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+7:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 7b
+
+ /* reset FIFO a second time */
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+8:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 8b
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+9:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 9b
+
+ /* enable power down timer */
+ ldr r7, [r10, #0x4]
+ orr r7, r7, #0x5500
+ str r7, [r10, #0x4]
+
+ /* enable DDR auto power saving */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Restore the TTBCR */
+
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* restore ttbr */
+ ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+/* imx6ul_low_power_idle */
+
+ .align 3
+ENTRY(imx6ul_low_power_idle)
+mx6ul_lpm_wfi_start:
+ push {r4 - r10}
+
+ /* get necessary info from pm_info */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r5, =imx6ul_low_power_idle
+ ldr r6, =wakeup
+ sub r6, r6, r5
+ add r8, r1, r2
+ add r3, r8, r6
+
+ /* store physical resume addr and pm_info address. */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
+ str r3, [r10, #0x20]
+ str r1, [r10, #0x24]
+
+ /* set ARM power to be gated */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r10, #0x2a0]
+
+ disable_l1_dcache
+
+ tlb_set_to_ocram
+
+ /* make sure MMDC in self-refresh */
+ ldr r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ mmdc_enter_dvfs_mode
+
+ /* save DDR IO settings */
+ ldr r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldr r6, =0x0
+ ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r8, r8, r0
+save_and_set_mmdc_io_lpm:
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ subs r7, r7, #0x1
+ bne save_and_set_mmdc_io_lpm
+
+ mov r5, #0x0
+ ccm_enter_idle
+ anatop_enter_idle
+
+ /*
+ * mask all GPC interrupts before
+ * enabling the RBC counters to
+ * avoid the counter starting too
+ * early if an interupt is already
+ * pending.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r4, [r10, #MX6Q_GPC_IMR1]
+ ldr r5, [r10, #MX6Q_GPC_IMR2]
+ ldr r6, [r10, #MX6Q_GPC_IMR3]
+ ldr r7, [r10, #MX6Q_GPC_IMR4]
+
+ ldr r3, =0xffffffff
+ str r3, [r10, #MX6Q_GPC_IMR1]
+ str r3, [r10, #MX6Q_GPC_IMR2]
+ str r3, [r10, #MX6Q_GPC_IMR3]
+ str r3, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 4 (120us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~130uS.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ bic r3, r3, #(0x3f << 21)
+ orr r3, r3, #(0x4 << 21)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* enable the counter. */
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ orr r3, r3, #(0x1 << 27)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* unmask all the GPC interrupts. */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ str r4, [r10, #MX6Q_GPC_IMR1]
+ str r5, [r10, #MX6Q_GPC_IMR2]
+ str r6, [r10, #MX6Q_GPC_IMR3]
+ str r7, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 24MHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r4, =50
+rbc_loop:
+ subs r4, r4, #0x1
+ bne rbc_loop
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mov r5, #0x0
+ anatop_exit_idle
+ ccm_exit_idle
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ resume_mmdc
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+ tlb_back_to_ddr
+
+ /* Restore registers */
+ pop {r4 - r10}
+ mov pc, lr
+
+wakeup:
+ /* invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0
+ isb
+
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ /* clear core0's entry and parameter */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
+ mov r7, #0x0
+ str r7, [r10, #MX6Q_SRC_GPR1]
+ str r7, [r10, #MX6Q_SRC_GPR2]
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ mov r5, #0x1
+ anatop_exit_idle
+ ccm_exit_idle
+ resume_mmdc
+
+ /* Restore registers */
+ mov pc, lr
+ .ltorg
+mx6ul_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/imx6ull_low_power_idle.S b/arch/arm/mach-imx/imx6ull_low_power_idle.S
new file mode 100644
index 000000000000..76ceac7fae26
--- /dev/null
+++ b/arch/arm/mach-imx/imx6ull_low_power_idle.S
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+
+#define PM_INFO_PBASE_OFFSET 0x0
+#define PM_INFO_RESUME_ADDR_OFFSET 0x4
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x8
+#define PM_INFO_PM_INFO_TTBR_OFFSET 0xc
+#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
+#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x18
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x1c
+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x20
+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x24
+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x28
+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x2c
+#define PM_INFO_MX6Q_ANATOP_P_OFFSET 0x30
+#define PM_INFO_MX6Q_ANATOP_V_OFFSET 0x34
+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x38
+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x3c
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44
+
+#define MX6Q_MMDC_MAPSR 0x404
+#define MX6Q_MMDC_MPDGCTRL0 0x83c
+#define MX6Q_SRC_GPR1 0x20
+#define MX6Q_SRC_GPR2 0x24
+#define MX6Q_GPC_IMR1 0x08
+#define MX6Q_GPC_IMR2 0x0c
+#define MX6Q_GPC_IMR3 0x10
+#define MX6Q_GPC_IMR4 0x14
+#define MX6Q_CCM_CCR 0x0
+
+.globl mx6ull_lpm_wfi_start
+.globl mx6ull_lpm_wfi_end
+
+ .macro pll_do_wait_lock
+1:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 1b
+
+ .endm
+
+ .macro ccm_do_wait
+2:
+ ldr r7, [r10, #0x48]
+ cmp r7, #0x0
+ bne 2b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+
+ /* set ahb to 3MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ /* set perclk to 6MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ orr r7, r7, #0x3
+ str r7, [r10, #0x1c]
+
+ /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
+ ldr r7, [r10, #0x14]
+ orr r7, r7, #0x2
+ orr r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * disable pll2, suppose when system enter low
+ * power idle mode, only 396MHz pfd needs pll2,
+ * now we switch arm clock to OSC, we can disable
+ * pll2 now, gate pll2_pfd2 first.
+ */
+ ldr r7, [r10, #0x100]
+ orr r7, #0x800000
+ str r7, [r10, #0x100]
+
+ ldr r7, [r10, #0x30]
+ orr r7, r7, #0x1000
+ bic r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* enable pll2 and pll2_pfd2 */
+ ldr r7, [r10, #0x30]
+ bic r7, r7, #0x1000
+ orr r7, r7, #0x2000
+ str r7, [r10, #0x30]
+
+ ldr r8, =0x30
+ pll_do_wait_lock
+
+ ldr r7, [r10, #0x100]
+ bic r7, #0x800000
+ str r7, [r10, #0x100]
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
+
+ /* set perclk back to 24MHz */
+ ldr r7, [r10, #0x1c]
+ bic r7, r7, #0x3f
+ str r7, [r10, #0x1c]
+
+ /* set mmdc back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x7
+ bic r7, r7, #(0x7 << 3)
+ str r7, [r10, #0x14]
+
+ /* set ahb div back to 24MHz */
+ ldr r7, [r10, #0x14]
+ bic r7, r7, #0x1c00
+ str r7, [r10, #0x14]
+
+ ccm_do_wait
+
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+
+ /*
+ * check whether any PLL is enabled, as only when
+ * there is no PLLs enabled, 2P5 and 1P1 can be
+ * off and only enable weak ones.
+ */
+
+ /* arm pll1 */
+ ldr r7, [r10, #0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* sys pll2 */
+ ldr r7, [r10, #0x30]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb pll3 */
+ ldr r7, [r10, #0x10]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* audio pll4 */
+ ldr r7, [r10, #0x70]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* vidio pll5 */
+ ldr r7, [r10, #0xa0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enet pll6 */
+ ldr r7, [r10, #0xe0]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* usb host pll7 */
+ ldr r7, [r10, #0x20]
+ ands r7, r7, #(1 << 31)
+ bne 10f
+
+ /* enable weak 2P5 and turn off regular 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x130]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* enable weak 1p1 and turn off regular 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x110]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x110]
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 10f
+
+ /* low power band gap enable */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x20
+ str r7, [r10, #0x270]
+
+ /* turn off the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /*
+ * clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn off regular bandgap */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x150]
+
+10:
+ /* switch to RC-OSC */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x40000000
+ str r7, [r10, #0x150]
+
+ /* lower OSC current by 37.5% */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* disconnect vdd_high_in and vdd_snvs_in */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x1000
+ str r7, [r10, #0x150]
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+
+ /* increase OSC current to normal */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x6000
+ str r7, [r10, #0x150]
+
+ /* turn on XTAL-OSC and detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x40000000
+ orr r7, r7, #0x10000
+ str r7, [r10, #0x150]
+
+ /* wait for XTAL stable */
+14:
+ ldr r7, [r10, #0x150]
+ ands r7, r7, #0x8000
+ beq 14b
+
+ /* switch to XTAL-OSC */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x10
+ str r7, [r10, #0x270]
+
+ /* turn off XTAL-OSC detector */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x10000
+ str r7, [r10, #0x150]
+15:
+ /* check whether we need to enable 2P5/1P1 */
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x40000
+ beq 11f
+
+ /* check whether ARM LDO is bypassed */
+ ldr r7, [r10, #0x140]
+ and r7, r7, #0x1f
+ cmp r7, #0x1f
+ bne 12f
+
+ /* turn on regular bandgap and wait for stable */
+ ldr r7, [r10, #0x150]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x150]
+13:
+ ldr r7, [r10, #0x150]
+ ands r7, #0x80
+ beq 13b
+
+ /*
+ * set the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ */
+ ldr r7, [r10, #0x150]
+ orr r7, r7, #0x8
+ str r7, [r10, #0x150]
+
+ /* turn on the bias current from the regular bandgap */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x80
+ str r7, [r10, #0x270]
+
+ /* low power band gap disable */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x20
+ str r7, [r10, #0x270]
+12:
+ /* enable regular 2P5 and turn off weak 2P5 */
+ ldr r7, [r10, #0x130]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x130]
+
+ /* Ensure the 2P5 is up. */
+3:
+ ldr r7, [r10, #0x130]
+ ands r7, r7, #0x20000
+ beq 3b
+ ldr r7, [r10, #0x130]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x130]
+
+ /* enable regular 1p1 and turn off weak 1P1 */
+ ldr r7, [r10, #0x110]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x110]
+4:
+ ldr r7, [r10, #0x110]
+ ands r7, r7, #0x20000
+ beq 4b
+ ldr r7, [r10, #0x110]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x110]
+11:
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro mmdc_enter_dvfs_mode
+
+ /* disable automatic power savings. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ /* disable power down timer */
+ ldr r7, [r10, #0x4]
+ bic r7, r7, #0xff00
+ str r7, [r10, #0x4]
+
+ /* make the DDR explicitly enter self-refresh. */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+5:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq 5b
+
+ .endm
+
+ .macro resume_mmdc
+
+ /* restore MMDC IO */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+6:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 6b
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
+
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+7:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 7b
+
+ /* reset FIFO a second time */
+ ldr r6, [r10, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r10, r7]
+8:
+ ldr r6, [r10, r7]
+ ands r6, r6, #(1 << 31)
+ bne 8b
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+9:
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 9b
+
+ /* enable power down timer */
+ ldr r7, [r10, #0x4]
+ orr r7, r7, #0x5500
+ str r7, [r10, #0x4]
+
+ /* enable DDR auto power saving */
+ ldr r7, [r10, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #MX6Q_MMDC_MAPSR]
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Restore the TTBCR */
+
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* restore ttbr */
+ ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+/* imx6ull_low_power_idle */
+
+ .align 3
+ENTRY(imx6ull_low_power_idle)
+mx6ull_lpm_wfi_start:
+ push {r4 - r10}
+
+ /* get necessary info from pm_info */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r5, =imx6ull_low_power_idle
+ ldr r6, =wakeup
+ sub r6, r6, r5
+ add r8, r1, r2
+ add r3, r8, r6
+
+ /* store physical resume addr and pm_info address. */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
+ str r3, [r10, #0x20]
+ str r1, [r10, #0x24]
+
+ /* set ARM power to be gated */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r10, #0x2a0]
+
+ disable_l1_dcache
+
+ tlb_set_to_ocram
+
+ /* make sure MMDC in self-refresh */
+ ldr r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ mmdc_enter_dvfs_mode
+
+ /* save DDR IO settings */
+ ldr r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldr r6, =0x0
+ ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r8, r8, r0
+save_and_set_mmdc_io_lpm:
+ ldr r9, [r8], #0x4
+ ldr r5, [r10, r9]
+ str r6, [r10, r9]
+ str r5, [r8], #0x4
+ subs r7, r7, #0x1
+ bne save_and_set_mmdc_io_lpm
+
+ mov r5, #0x0
+ ccm_enter_idle
+ anatop_enter_idle
+
+ /*
+ * mask all GPC interrupts before
+ * enabling the RBC counters to
+ * avoid the counter starting too
+ * early if an interupt is already
+ * pending.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r4, [r10, #MX6Q_GPC_IMR1]
+ ldr r5, [r10, #MX6Q_GPC_IMR2]
+ ldr r6, [r10, #MX6Q_GPC_IMR3]
+ ldr r7, [r10, #MX6Q_GPC_IMR4]
+
+ ldr r3, =0xffffffff
+ str r3, [r10, #MX6Q_GPC_IMR1]
+ str r3, [r10, #MX6Q_GPC_IMR2]
+ str r3, [r10, #MX6Q_GPC_IMR3]
+ str r3, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 4 (120us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~130uS.
+ */
+ ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ bic r3, r3, #(0x3f << 21)
+ orr r3, r3, #(0x4 << 21)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* enable the counter. */
+ ldr r3, [r10, #MX6Q_CCM_CCR]
+ orr r3, r3, #(0x1 << 27)
+ str r3, [r10, #MX6Q_CCM_CCR]
+
+ /* unmask all the GPC interrupts. */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ str r4, [r10, #MX6Q_GPC_IMR1]
+ str r5, [r10, #MX6Q_GPC_IMR2]
+ str r6, [r10, #MX6Q_GPC_IMR3]
+ str r7, [r10, #MX6Q_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 24MHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r4, =50
+rbc_loop:
+ subs r4, r4, #0x1
+ bne rbc_loop
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mov r5, #0x0
+ anatop_exit_idle
+ ccm_exit_idle
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ resume_mmdc
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+
+ tlb_back_to_ddr
+
+ /* Restore registers */
+ pop {r4 - r10}
+ mov pc, lr
+
+wakeup:
+ /* invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0
+ isb
+
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ /* clear core0's entry and parameter */
+ ldr r10, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
+ mov r7, #0x0
+ str r7, [r10, #MX6Q_SRC_GPR1]
+ str r7, [r10, #MX6Q_SRC_GPR2]
+
+ /* clear ARM power gate setting */
+ ldr r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
+ ldr r7, =0x0
+ str r7, [r10, #0x2a0]
+
+ mov r5, #0x1
+ anatop_exit_idle
+ ccm_exit_idle
+ resume_mmdc
+
+ /* Restore registers */
+ mov pc, lr
+ .ltorg
+mx6ull_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/imx7d_low_power_idle.S b/arch/arm/mach-imx/imx7d_low_power_idle.S
new file mode 100644
index 000000000000..85c229700ec4
--- /dev/null
+++ b/arch/arm/mach-imx/imx7d_low_power_idle.S
@@ -0,0 +1,788 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+
+#define PM_INFO_VBASE_OFFSET 0x0
+#define PM_INFO_PBASE_OFFSET 0x4
+#define PM_INFO_RESUME_ADDR_OFFSET 0x8
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0xc
+#define PM_INFO_PM_INFO_TTBR_OFFSET 0x10
+#define PM_INFO_PM_INFO_NUM_ONLINE_CPUS_OFFSET 0x14
+#define PM_INFO_PM_INFO_NUM_LPI_CPUS_OFFSET 0x18
+#define PM_INFO_VAL_OFFSET 0x1c
+#define PM_INFO_FLAG0_OFFSET 0x20
+#define PM_INFO_FLAG1_OFFSET 0x24
+#define PM_INFO_MX7D_DDRC_P_OFFSET 0x28
+#define PM_INFO_MX7D_DDRC_V_OFFSET 0x2c
+#define PM_INFO_MX7D_CCM_P_OFFSET 0x30
+#define PM_INFO_MX7D_CCM_V_OFFSET 0x34
+#define PM_INFO_MX7D_ANATOP_P_OFFSET 0x38
+#define PM_INFO_MX7D_ANATOP_V_OFFSET 0x3c
+#define PM_INFO_MX7D_SRC_P_OFFSET 0x40
+#define PM_INFO_MX7D_SRC_V_OFFSET 0x44
+#define PM_INFO_MX7D_IOMUXC_GPR_P_OFFSET 0x48
+#define PM_INFO_MX7D_IOMUXC_GPR_V_OFFSET 0x4c
+#define PM_INFO_MX7D_GPC_P_OFFSET 0x50
+#define PM_INFO_MX7D_GPC_V_OFFSET 0x54
+#define PM_INFO_MX7D_GIC_DIST_P_OFFSET 0x58
+#define PM_INFO_MX7D_GIC_DIST_V_OFFSET 0x5c
+
+#define MX7D_SRC_GPR1 0x74
+#define MX7D_SRC_GPR2 0x78
+#define MX7D_SRC_GPR3 0x7c
+#define MX7D_SRC_GPR4 0x80
+#define MX7D_GPC_IMR1 0x30
+#define MX7D_GPC_IMR2 0x34
+#define MX7D_GPC_IMR3 0x38
+#define MX7D_GPC_IMR4 0x3c
+#define DDRC_STAT 0x4
+#define DDRC_PWRCTL 0x30
+#define DDRC_DBG1 0x304
+#define DDRC_DBGCAM 0x308
+#define DDRC_PSTAT 0x3fc
+#define DDRC_PCTRL_0 0x490
+
+/*
+ * imx_pen_lock
+ *
+ * The reference link of Peterson's algorithm:
+ * http://en.wikipedia.org/wiki/Peterson's_algorithm
+ *
+ * val1 = r1 = !turn (inverted from Peterson's algorithm)
+ * on cpu 0:
+ * r2 = flag[0] (in flag0)
+ * r3 = flag[1] (in flag1)
+ * on cpu1:
+ * r2 = flag[1] (in flag1)
+ * r3 = flag[0] (in flag0)
+ *
+ */
+ .macro imx_pen_lock
+
+ mov r8, r0
+ mrc p15, 0, r5, c0, c0, 5
+ and r5, r5, #3
+ add r6, r8, #PM_INFO_VAL_OFFSET
+ cmp r5, #0
+ addeq r7, r8, #PM_INFO_FLAG0_OFFSET
+ addeq r8, r8, #PM_INFO_FLAG1_OFFSET
+ addne r7, r8, #PM_INFO_FLAG1_OFFSET
+ addne r8, r8, #PM_INFO_FLAG0_OFFSET
+
+ mov r9, #1
+ str r9, [r7]
+ dsb
+ str r5, [r6]
+1:
+ dsb
+ ldr r9, [r8]
+ cmp r9, #1
+ ldreq r9, [r6]
+ cmpeq r9, r5
+ beq 1b
+
+ .endm
+
+ .macro imx_pen_unlock
+
+ dsb
+ mrc p15, 0, r6, c0, c0, 5
+ and r6, r6, #3
+ cmp r6, #0
+ addeq r7, r0, #PM_INFO_FLAG0_OFFSET
+ addne r7, r0, #PM_INFO_FLAG1_OFFSET
+ mov r9, #0
+ str r9, [r7]
+
+ .endm
+
+ .macro disable_l1_dcache
+
+ push {r0 - r12, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r12, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r12, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r12, lr}
+
+#ifdef CONFIG_SMP
+ clrex
+
+ /* Turn off SMP bit. */
+ mrc p15, 0, r8, c1, c0, 1
+ bic r8, r8, #0x40
+ mcr p15, 0, r8, c1, c0, 1
+
+ isb
+ dsb
+#endif
+
+ .endm
+
+ .macro tlb_set_to_ocram
+
+ /* save ttbr */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro tlb_back_to_ddr
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* restore ttbr */
+ ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+ /* r10 must be DDRC base address */
+ .macro ddrc_enter_self_refresh
+
+ ldr r10, [r0, #PM_INFO_MX7D_DDRC_V_OFFSET]
+
+ /* disable port */
+ ldr r7, =0x0
+ str r7, [r10, #DDRC_PCTRL_0]
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r10, #DDRC_PWRCTL]
+
+ /* wait rw port_busy clear */
+ ldr r6, =(0x1 << 16)
+ orr r6, r6, #0x1
+2:
+ ldr r7, [r10, #DDRC_PSTAT]
+ ands r7, r7, r6
+ bne 2b
+
+ ldr r7, =0x1
+ str r7, [r10, #DDRC_DBG1]
+
+ ldr r6, =0x36000000
+11:
+ ldr r7, [r10, #DDRC_DBGCAM]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 11b
+
+ /* enter self-refresh bit 5 */
+ ldr r7, =(0x1 << 5)
+ str r7, [r10, #DDRC_PWRCTL]
+
+ /* wait until self-refresh mode entered */
+3:
+ ldr r7, [r10, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ bne 3b
+4:
+ ldr r7, [r10, #DDRC_STAT]
+ ands r7, r7, #0x20
+ beq 4b
+
+ /* disable dram clk */
+ ldr r7, [r10, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 3)
+ str r7, [r10, #DDRC_PWRCTL]
+
+ /*
+ * TO1.1 adds feature of DDR pads power down,
+ * although TO1.0 has no such function, but it is
+ * NOT harmful to program GPR registers for TO1.0,
+ * it can avoid the logic of version check in idle
+ * thread.
+ */
+ ldr r10, [r0, #PM_INFO_MX7D_IOMUXC_GPR_V_OFFSET]
+ ldr r7, =0xf0000
+ str r7, [r10]
+
+ /* delay 20us, measured by gpio */
+ ldr r7, =20
+12:
+ subs r7, r7, #0x1
+ bne 12b
+
+ .endm
+
+ /* r10 must be DDRC base address */
+ .macro ddrc_exit_self_refresh
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_IOMUXC_GPR_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_IOMUXC_GPR_V_OFFSET]
+
+ ldr r7, =0x0
+ str r7, [r10]
+
+ ldr r7, =20
+13:
+ subs r7, r7, #0x1
+ bne 13b
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_DDRC_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_DDRC_V_OFFSET]
+
+ ldr r7, =0x0
+ str r7, [r10, #DDRC_DBG1]
+
+ ldr r6, =0x30000000
+14:
+ ldr r7, [r10, #DDRC_DBGCAM]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 14b
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r10, #DDRC_PWRCTL]
+
+ /* wait until self-refresh mode exited */
+5:
+ ldr r7, [r10, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ beq 5b
+
+ /* enable auto self-refresh */
+ ldr r7, [r10, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r10, #DDRC_PWRCTL]
+
+ ldr r7, =0x1
+ str r7, [r10, #DDRC_PCTRL_0]
+
+ .endm
+
+ .macro pll_do_wait_lock
+6:
+ ldr r7, [r10, r8]
+ ands r7, #0x80000000
+ beq 6b
+
+ .endm
+
+ .macro ccm_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* ungate pfd1 332m for lower axi */
+ ldr r7, =0x8000
+ str r7, [r10, #0xc8]
+
+ ldr r10, [r0, #PM_INFO_MX7D_CCM_V_OFFSET]
+
+ /* switch ARM CLK to OSC */
+ ldr r8, =0x8000
+ ldr r7, [r10, r8]
+ bic r7, r7, #0x7000000
+ str r7, [r10, r8]
+
+ /* lower AXI clk from 24MHz to 3MHz */
+ ldr r8, =0x8800
+ ldr r7, [r10, r8]
+ orr r7, r7, #0x7
+ str r7, [r10, r8]
+
+ /* lower AHB clk from 24MHz to 3MHz */
+ ldr r8, =0x9000
+ ldr r7, [r10, r8]
+ orr r7, r7, #0x7
+ str r7, [r10, r8]
+
+ /* gate dram clk */
+ ldr r8, =0x9880
+ ldr r7, [r10, r8]
+ bic r7, r7, #0x10000000
+ str r7, [r10, r8]
+
+ ldr r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* gate pfd1 332m */
+ ldr r7, =0x8000
+ str r7, [r10, #0xc4]
+
+ /* gate system pll pfd div 1 */
+ ldr r7, =0x10
+ str r7, [r10, #0xb4]
+ /* power down ARM, 480 and DRAM PLL */
+ ldr r7, =0x1000
+ str r7, [r10, #0x64]
+ str r7, [r10, #0xb4]
+ ldr r7, =0x100000
+ str r7, [r10, #0x74]
+
+ .endm
+
+ .macro ccm_exit_idle
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_ANATOP_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* power up ARM, 480 and DRAM PLL */
+ ldr r7, =0x1000
+ str r7, [r10, #0x68]
+ ldr r8, =0x60
+ pll_do_wait_lock
+
+ ldr r7, =0x1000
+ str r7, [r10, #0xb8]
+ ldr r8, =0xb0
+ pll_do_wait_lock
+
+ ldr r7, =0x100000
+ str r7, [r10, #0x78]
+ ldr r8, =0x70
+ pll_do_wait_lock
+
+ /* ungate pfd1 332m for lower axi */
+ ldr r7, =0x8000
+ str r7, [r10, #0xc8]
+
+ /* ungate system pll pfd div 1 */
+ ldr r7, =0x10
+ str r7, [r10, #0xb8]
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_CCM_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_CCM_V_OFFSET]
+
+ /* switch ARM CLK to PLL */
+ ldr r8, =0x8000
+ ldr r7, [r10, r8]
+ orr r7, r7, #0x1000000
+ str r7, [r10, r8]
+
+ /* restore AXI clk from 3MHz to 24MHz */
+ ldr r8, =0x8800
+ ldr r7, [r10, r8]
+ bic r7, r7, #0x7
+ str r7, [r10, r8]
+
+ /* restore AHB clk from 3MHz to 24MHz */
+ ldr r8, =0x9000
+ ldr r7, [r10, r8]
+ bic r7, r7, #0x7
+ str r7, [r10, r8]
+
+ /* ungate dram clk */
+ ldr r8, =0x9880
+ ldr r7, [r10, r8]
+ orr r7, r7, #0x10000000
+ str r7, [r10, r8]
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_ANATOP_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* gate pfd1 332m for lower axi */
+ ldr r7, =0x8000
+ str r7, [r10, #0xc4]
+
+ .endm
+
+ .macro anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* XTAL to RC-OSC switch */
+ ldr r7, [r10]
+ orr r7, r7, #0x1000
+ str r7, [r10]
+ /* power down XTAL */
+ ldr r7, [r10]
+ orr r7, r7, #0x1
+ str r7, [r10]
+
+ /* enable weak 1P0A */
+ ldr r7, [r10, #0x200]
+ orr r7, r7, #0x40000
+ str r7, [r10, #0x200]
+
+ /* disable LDO 1P0A */
+ ldr r7, [r10, #0x200]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x200]
+
+ /* disable LDO 1P0D */
+ ldr r7, [r10, #0x210]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x210]
+
+ /* disable LDO 1P2 */
+ ldr r7, [r10, #0x220]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x220]
+
+ /* switch to low power bandgap */
+ ldr r7, [r10, #0x270]
+ orr r7, r7, #0x400
+ str r7, [r10, #0x270]
+ /* power down normal bandgap */
+ orr r7, r7, #0x1
+ str r7, [r10, #0x270]
+
+ .endm
+
+ .macro anatop_exit_idle
+
+ cmp r5, #0x1
+ ldreq r10, [r0, #PM_INFO_MX7D_ANATOP_P_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7D_ANATOP_V_OFFSET]
+
+ /* power on normal bandgap */
+ ldr r7, [r10, #0x270]
+ bic r7, r7, #0x1
+ str r7, [r10, #0x270]
+ /* switch to normal bandgap */
+ bic r7, r7, #0x400
+ str r7, [r10, #0x270]
+
+ /* enable LDO 1P2 */
+ ldr r7, [r10, #0x220]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x220]
+7:
+ ldr r7, [r10, #0x220]
+ ands r7, #0x20000
+ beq 7b
+
+ /* enable LDO 1P0D */
+ ldr r7, [r10, #0x210]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x210]
+8:
+ ldr r7, [r10, #0x210]
+ ands r7, #0x20000
+ beq 8b
+
+ /* enable LDO 1P0A */
+ ldr r7, [r10, #0x200]
+ orr r7, r7, #0x1
+ str r7, [r10, #0x200]
+9:
+ ldr r7, [r10, #0x200]
+ ands r7, #0x20000
+ beq 9b
+ /* disable weak 1P0A */
+ ldr r7, [r10, #0x200]
+ bic r7, r7, #0x40000
+ str r7, [r10, #0x200]
+
+ /* power up XTAL and wait */
+ ldr r7, [r10]
+ bic r7, r7, #0x1
+ str r7, [r10]
+10:
+ ldr r7, [r10]
+ ands r7, r7, #0x4
+ beq 10b
+ /* RC-OSC to XTAL switch */
+ ldr r7, [r10]
+ bic r7, r7, #0x1000
+ str r7, [r10]
+
+ .endm
+
+.extern iram_tlb_phys_addr
+
+ .align 3
+ENTRY(imx7d_low_power_idle)
+ push {r0 - r12}
+
+ /* get necessary info from pm_info */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r5, =imx7d_low_power_idle
+ ldr r6, =wakeup
+ sub r6, r6, r5
+ add r8, r1, r2
+ add r3, r8, r6
+
+ /* r11 is cpu id */
+ mrc p15, 0, r11, c0, c0, 5
+ and r11, r11, #3
+ cmp r11, #0x0
+ ldreq r6, =MX7D_SRC_GPR1
+ ldreq r7, =MX7D_SRC_GPR2
+ ldrne r6, =MX7D_SRC_GPR3
+ ldrne r7, =MX7D_SRC_GPR4
+ /* store physical resume addr and pm_info address. */
+ ldr r10, [r0, #PM_INFO_MX7D_SRC_V_OFFSET]
+ str r3, [r10, r6]
+ str r1, [r10, r7]
+
+ disable_l1_dcache
+
+ tlb_set_to_ocram
+
+ /* check last to sleep */
+ ldr r6, [r0, #PM_INFO_PM_INFO_NUM_ONLINE_CPUS_OFFSET]
+ ldr r7, [r0, #PM_INFO_PM_INFO_NUM_LPI_CPUS_OFFSET]
+ cmp r6, r7
+ bne lpi_enter_done
+
+ ddrc_enter_self_refresh
+ ccm_enter_idle
+ anatop_enter_idle
+
+ ldr r10, [r0, #PM_INFO_MX7D_GIC_DIST_V_OFFSET]
+ ldr r7, =0x0
+ ldr r8, =0x1000
+ str r7, [r10, r8]
+
+ ldr r10, [r0, #PM_INFO_MX7D_GPC_V_OFFSET]
+ ldr r4, [r10, #MX7D_GPC_IMR1]
+ ldr r5, [r10, #MX7D_GPC_IMR2]
+ ldr r6, [r10, #MX7D_GPC_IMR3]
+ ldr r7, [r10, #MX7D_GPC_IMR4]
+
+ ldr r8, =0xffffffff
+ str r8, [r10, #MX7D_GPC_IMR1]
+ str r8, [r10, #MX7D_GPC_IMR2]
+ str r8, [r10, #MX7D_GPC_IMR3]
+ str r8, [r10, #MX7D_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 8 (240us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~250uS.
+ */
+ ldr r8, [r10, #0x14]
+ bic r8, r8, #(0x3f << 24)
+ orr r8, r8, #(0x8 << 24)
+ str r8, [r10, #0x14]
+
+ /* enable the counter. */
+ ldr r8, [r10, #0x14]
+ orr r8, r8, #(0x1 << 30)
+ str r8, [r10, #0x14]
+
+ /* unmask all the GPC interrupts. */
+ str r4, [r10, #MX7D_GPC_IMR1]
+ str r5, [r10, #MX7D_GPC_IMR2]
+ str r6, [r10, #MX7D_GPC_IMR3]
+ str r7, [r10, #MX7D_GPC_IMR4]
+
+ /*
+ * now delay for a short while (30usec)
+ * ARM is at 24MHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r4, =5
+rbc_loop:
+ subs r4, r4, #0x1
+ bne rbc_loop
+
+lpi_enter_done:
+
+ imx_pen_unlock
+
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ imx_pen_lock
+
+ /* check first to wake */
+ ldr r6, [r0, #PM_INFO_PM_INFO_NUM_ONLINE_CPUS_OFFSET]
+ ldr r7, [r0, #PM_INFO_PM_INFO_NUM_LPI_CPUS_OFFSET]
+ cmp r6, r7
+ bne skip_lpi_flow
+
+ ldr r5, =0x0
+ anatop_exit_idle
+ ccm_exit_idle
+ ddrc_exit_self_refresh
+
+ ldr r10, [r0, #PM_INFO_MX7D_GIC_DIST_V_OFFSET]
+ ldr r7, =0x1
+ ldr r8, =0x1000
+ str r7, [r10, r8]
+
+skip_lpi_flow:
+ tlb_back_to_ddr
+
+#ifdef CONFIG_SMP
+ /* Turn on SMP bit. */
+ mrc p15, 0, r7, c1, c0, 1
+ orr r7, r7, #0x40
+ mcr p15, 0, r7, c1, c0, 1
+
+ isb
+#endif
+
+ /* enable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ /* Restore registers */
+ pop {r0 - r12}
+ mov pc, lr
+
+wakeup:
+
+ /* invalidate L1 I-cache first */
+ mov r1, #0x0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 0
+ mcr p15, 0, r1, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r1, #0x1800
+ mcr p15, 0, r1, c1, c0, 0
+ isb
+
+ imx_pen_lock
+
+ /* check first to wake */
+ ldr r6, [r0, #PM_INFO_PM_INFO_NUM_ONLINE_CPUS_OFFSET]
+ ldr r7, [r0, #PM_INFO_PM_INFO_NUM_LPI_CPUS_OFFSET]
+ cmp r6, r7
+ bne wakeup_skip_lpi_flow
+
+ ldr r5, =0x1
+ anatop_exit_idle
+ ccm_exit_idle
+ ddrc_exit_self_refresh
+
+wakeup_skip_lpi_flow:
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+
+ /* Restore registers */
+ mov pc, lr
+ .ltorg
+ENDPROC(imx7d_low_power_idle)
diff --git a/arch/arm/mach-imx/lpddr2_freq_imx6.S b/arch/arm/mach-imx/lpddr2_freq_imx6.S
new file mode 100644
index 000000000000..21179fb2cb72
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6.S
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2012-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+#define PL310_AUX_CTRL 0x104
+#define PL310_DCACHE_LOCKDOWN_BASE 0x900
+#define PL310_AUX_16WAY_BIT 0x10000
+#define PL310_LOCKDOWN_NBREGS 8
+#define PL310_LOCKDOWN_SZREG 4
+#define PL310_8WAYS_MASK 0x00FF
+#define PL310_16WAYS_UPPERMASK 0xFF00
+
+.globl imx6_lpddr2_freq_change_start
+.globl imx6_lpddr2_freq_change_end
+
+ .macro mx6sl_switch_to_24MHz
+
+ /*
+ * Set MMDC clock to be sourced from PLL3.
+ * Ensure first periph2_clk2 is sourced from PLL3.
+ * Set the PERIPH2_CLK2_PODF to divide by 2.
+ */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x7
+ orr r6, r6, #0x1
+ str r6, [r2, #0x14]
+
+ /* Select PLL3 to source MMDC. */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* Swtich periph2_clk_sel to run from PLL3. */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch1
+
+ /*
+ * Need to clock gate the 528 PFDs before
+ * powering down PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * at this time, so only clock gate that one.
+ */
+ ldr r6, [r3, #0x100]
+ orr r6, r6, #0x800000
+ str r6, [r3, #0x100]
+
+ /*
+ * Set PLL2 to bypass state. We should be here
+ * only if MMDC is not sourced from PLL2.
+ */
+ ldr r6, [r3, #0x30]
+ orr r6, r6, #0x10000
+ str r6, [r3, #0x30]
+
+ ldr r6, [r3, #0x30]
+ orr r6, r6, #0x1000
+ str r6, [r3, #0x30]
+
+ /* Ensure pre_periph2_clk_mux is set to pll2 */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x600000
+ str r6, [r2, #0x18]
+
+ /* Set MMDC clock to be sourced from the bypassed PLL2. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch2:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch2
+
+ /*
+ * Now move MMDC back to periph2_clk2 source.
+ * after selecting PLL2 as the option.
+ * Select PLL2 as the source.
+ */
+ ldr r6, [r2, #0x18]
+ orr r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* set periph2_clk2_podf to divide by 1. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x7
+ str r6, [r2, #0x14]
+
+ /* Now move periph2_clk to periph2_clk2 source */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch3:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch3
+
+ /* Now set the MMDC PODF back to 1.*/
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r2, #0x14]
+
+mmdc_podf0:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf0
+
+ .endm
+
+ .macro ddr_switch_400MHz
+
+ /* Set MMDC divider first, in case PLL3 is at 480MHz. */
+ ldr r6, [r3, #0x10]
+ and r6, r6, #0x10000
+ cmp r6, #0x10000
+ beq pll3_in_bypass
+
+ /* Set MMDC divder to divide by 2. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, #0x8
+ str r6, [r2, #0x14]
+
+mmdc_podf:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf
+
+pll3_in_bypass:
+ /*
+ * Check if we are switching between
+ * 400Mhz <-> 100MHz.If so, we should
+ * try to source MMDC from PLL2_200M.
+ */
+ cmp r1, #0
+ beq not_low_bus_freq
+
+ /* Ensure that MMDC is sourced from PLL2 mux first. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch4:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch4
+
+not_low_bus_freq:
+ /* Now ensure periph2_clk2_sel mux is set to PLL3 */
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x100000
+ str r6, [r2, #0x18]
+
+ /* Now switch MMDC to PLL3. */
+ ldr r6, [r2, #0x14]
+ orr r6, r6, #0x4000000
+ str r6, [r2, #0x14]
+
+periph2_clk_switch5:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne periph2_clk_switch5
+
+ /*
+ * Check if PLL2 is already unlocked.
+ * If so do nothing with PLL2.
+ */
+ cmp r1, #0
+ beq pll2_already_on
+
+ /* Now power up PLL2 and unbypass it. */
+ ldr r6, [r3, #0x30]
+ bic r6, r6, #0x1000
+ str r6, [r3, #0x30]
+
+ /* Make sure PLL2 has locked.*/
+wait_for_pll_lock:
+ ldr r6, [r3, #0x30]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+ ldr r6, [r3, #0x30]
+ bic r6, r6, #0x10000
+ str r6, [r3, #0x30]
+
+ /*
+ * Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r3, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r3, #0x100]
+
+pll2_already_on:
+ /*
+ * Now switch MMDC clk back to pll2_mux option.
+ * Ensure pre_periph2_clk2 is set to pll2_pfd_400M.
+ * If switching to audio DDR freq, set the
+ * pre_periph2_clk2 to PLL2_PFD_200M
+ */
+ ldr r6, =400000000
+ cmp r6, r0
+ bne use_pll2_pfd_200M
+
+ ldr r6, [r2, #0x18]
+ bic r6, r6, #0x600000
+ orr r6, r6, #0x200000
+ str r6, [r2, #0x18]
+ ldr r6, =400000000
+ b cont2
+
+use_pll2_pfd_200M:
+ ldr r6, [r2, #0x18]
+ orr r6, r6, #0x600000
+ str r6, [r2, #0x18]
+ ldr r6, =200000000
+
+cont2:
+ ldr r4, [r2, #0x14]
+ bic r4, r4, #0x4000000
+ str r4, [r2, #0x14]
+
+periph2_clk_switch6:
+ ldr r4, [r2, #0x48]
+ cmp r4, #0
+ bne periph2_clk_switch6
+
+change_divider_only:
+ /*
+ * Calculate the MMDC divider
+ * based on the requested freq.
+ */
+ ldr r4, =0
+Loop2:
+ sub r6, r6, r0
+ cmp r6, r0
+ blt Div_Found
+ add r4, r4, #1
+ bgt Loop2
+
+ /* Shift divider into correct offset. */
+ lsl r4, r4, #3
+Div_Found:
+ /* Set the MMDC PODF. */
+ ldr r6, [r2, #0x14]
+ bic r6, r6, #0x38
+ orr r6, r6, r4
+ str r6, [r2, #0x14]
+
+mmdc_podf1:
+ ldr r6, [r2, #0x48]
+ cmp r6, #0
+ bne mmdc_podf1
+
+ .endm
+
+ .macro mmdc_clk_lower_100MHz
+
+ /*
+ * Prior to reducing the DDR frequency (at 528/400 MHz),
+ * read the Measure unit count bits (MU_UNIT_DEL_NUM)
+ */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r4, =0x3FF
+ and r6, r6, r4
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /*
+ * Bypass the automatic measure unit when below 100 MHz
+ * by setting the Measure unit bypass enable bit (MU_BYP_EN)
+ */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x400
+ str r6, [r8, r5]
+ /*
+ * Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r8, r5]
+ ldr r4, =0x3FF
+ bic r6, r6, r4
+ orr r6, r6, r7
+ str r6, [r8, r5]
+
+ .endm
+
+ .macro mmdc_clk_above_100MHz
+
+ /* Make sure that the PHY measurement unit is NOT in bypass mode */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ bic r6, r6, #0x400
+ str r6, [r8, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x800
+ str r6, [r8, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure1:
+ ldr r6, [r8, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1
+ .endm
+
+/*
+ * mx6_lpddr2_freq_change
+ *
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ * r0 : DDR freq.
+ * r1: low_bus_freq_mode flag
+ */
+ .align 3
+ENTRY(mx6_lpddr2_freq_change)
+imx6_lpddr2_freq_change_start:
+ push {r4-r10}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Need to make sure the buffers in L2 are drained.
+ * Performing a sync operation does this.
+ */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r6, [r7, #0x730]
+ cmp r6, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r6, #0x0
+ str r6, [r7, #0x730]
+
+ /*
+ * The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r3, #PL310_8WAYS_MASK
+ orrne r3, #PL310_16WAYS_UPPERMASK
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+ ldr r3, =IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR)
+ ldr r2, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r8, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* MMDC0_MDPDC disable power down timer */
+ ldr r6, [r8, #0x4]
+ bic r6, r6, #0xff00
+ str r6, [r8, #0x4]
+
+ /* Delay for a while */
+ ldr r10, =10
+delay1:
+ ldr r7, =0
+cont1:
+ ldr r6, [r8, r7]
+ add r7, r7, #4
+ cmp r7, #16
+ bne cont1
+ sub r10, r10, #1
+ cmp r10, #0
+ bgt delay1
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_set_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r8, #0x410]
+ orr r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ ldr r10, =100000000
+ cmp r0, r10
+ bgt set_ddr_mu_above_100
+ mmdc_clk_lower_100MHz
+
+set_ddr_mu_above_100:
+ ldr r10, =24000000
+ cmp r0, r10
+ beq set_to_24MHz
+
+ ddr_switch_400MHz
+
+ ldr r10,=100000000
+ cmp r0, r10
+ blt done
+ mmdc_clk_above_100MHz
+
+ b done
+
+set_to_24MHz:
+ mx6sl_switch_to_24MHz
+
+done:
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ ldr r10, =24000000
+ cmp r0, r10
+ beq skip_power_down
+
+ /* Enable MMDC power down timer. */
+ ldr r6, [r8, #0x4]
+ orr r6, r6, #0x5500
+ str r6, [r8, #0x4]
+
+skip_power_down:
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r8, #0x410]
+ bic r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ mov r3, #0x00 /* 8 ways mask */
+ orrne r3, #0x0000 /* 16 ways mask */
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ pop {r4-r10}
+
+ /* Restore registers */
+ mov pc, lr
+
+ /*
+ * Add ltorg here to ensure that all
+ * literals are stored here and are
+ * within the text space.
+ */
+ .ltorg
+imx6_lpddr2_freq_change_end:
diff --git a/arch/arm/mach-imx/lpddr2_freq_imx6q.S b/arch/arm/mach-imx/lpddr2_freq_imx6q.S
new file mode 100644
index 000000000000..6c9aac07df16
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6q.S
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include <asm/smp_scu.h>
+#include "hardware.h"
+
+#define CCM_CBCDR 0x14
+#define CCM_CBCMR 0x18
+#define CCM_CSCMR1 0x1c
+#define CCM_CDHIPR 0x48
+
+.globl mx6q_lpddr2_freq_change_start
+.globl mx6q_lpddr2_freq_change_end
+
+ .macro wait_for_ccm_handshake
+ /* wait for div update */
+1:
+ ldr r9, [r2, #CCM_CDHIPR]
+ cmp r9, #0
+ bne 1b
+
+ .endm
+
+ .macro set_mmdc_misc_ralat_2_cycles
+
+ /* Set MMDCx_MISC[RALAT] = 2 cycles */
+ ldr r6, [r8, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x2 << 6)
+ str r6, [r8, #0x18]
+
+ /* Check if lpddr2 channel 1 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq 1f
+
+ ldr r6, [r4, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x2 << 6)
+ str r6, [r4, #0x18]
+1:
+ .endm
+
+ .macro switch_to_400MHz
+ /* set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3 */
+ ldr r9, [r2, #CCM_CBCDR]
+ ldr r6, =0x3f1f00
+ bic r9, r9, r6
+ orr r9, r9, #(0x9 << 8)
+ orr r9, r9, #(1 << 16)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* check periph_clk_sel */
+ ldr r9, [r2, #CCM_CBCDR]
+ and r9, r9, #(1 << 25)
+ cmp r9, #(1 << 25)
+ bne skip_periph_clk_switch_400m
+
+ /* now switch periph_clk back. */
+ ldr r9, [r2, #CCM_CBCDR]
+ bic r9, r9, #(1 << 25)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+skip_periph_clk_switch_400m:
+
+ .endm
+
+ .macro switch_to_100MHz
+ /* set the MMDC_DIV=4, AXI_DIV=8, AHB_DIV=8 */
+ ldr r9, [r2, #CCM_CBCDR]
+ ldr r6, =0x3f1f00
+ bic r9, r9, r6
+ orr r9, r9, #(0x1F << 16)
+ orr r9, r9, #(0x1D << 8)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* check if periph_clk_sel is already set. */
+ ldr r9, [r2, #CCM_CBCDR]
+ and r9, r9, #(1 << 25)
+ cmp r9, #(1 << 25)
+ bne skip_periph_clk_switch_100m
+
+ /* now switch periph_clk back. */
+ ldr r9, [r2, #CCM_CBCDR]
+ bic r9, r9, #(1 << 25)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+skip_periph_clk_switch_100m:
+
+ .endm
+
+ .macro switch_to_24MHz
+ /*
+ * change the freq now try setting DDR to 24MHz.
+ * source it from the periph_clk2 ensure the
+ * periph_clk2 is sourced from 24MHz and the
+ * divider is 1.
+ */
+
+ ldr r9, [r2, #CCM_CBCMR]
+ bic r9, r9, #(0x3 << 12)
+ orr r9, r9, #(1 << 12)
+ str r9, [r2, #CCM_CBCMR]
+
+ ldr r9, [r2, #CCM_CBCDR]
+ bic r9, r9, #(0x7 << 27)
+ str r9, [r2, #CCM_CBCDR]
+
+ /* now switch periph_clk to 24MHz. */
+ ldr r9, [r2, #CCM_CBCDR]
+ orr r9, r9, #(1 << 25)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* change all the dividers to 1. */
+ ldr r9, [r2, #CCM_CBCDR]
+ ldr r6, =0x3f1f00
+ bic r9, r9, r6
+ orr r9, r9, #(1 << 8)
+ str r9, [r2, #CCM_CBCDR]
+
+ /* Wait for the divider to change. */
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_24MHZ_from_pll2
+ /* Change DDR freq settings from pll2_pfd2 (div 2) */
+
+ ldr r9, [r2, #CCM_CBCMR]
+ bic r9, r9, #(0x3 << 18)
+ orr r9, r9, #(0x3 << 18)
+ str r9, [r2, #CCM_CBCMR]
+
+ ldr r9, [r2, #CCM_CBCDR]
+ bic r9, r9, #(1 << 25)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ ldr r9, [r2, #CCM_CBCDR]
+ ldr r6, =0x3f1f00
+ bic r9, r9, r6
+ orr r9, r9, #(1 << 8)
+ orr r9, r9, #(0x7 << 19)
+ str r9, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro set_timings_below_100MHz_operation
+ set_mmdc_misc_ralat_2_cycles
+
+ /* Adjust LPDDR2 timings for 24Mhz operation */
+ ldr r5, =0x03162073
+ str r5, [r8, #0xC] /* MMDC0_MDCFG0 */
+ ldr r7, =0x00020482
+ str r7, [r8, #0x10] /* MMDC0_MDCFG1 */
+ ldr r9, =0x00000049
+ str r9, [r8, #0x14] /* MMDC0_MDCFG2 */
+ ldr r10, =0x00020333
+ str r10, [r8, #0x38] /* MMDC0_MDCFG3LP */
+
+ /* Check if lpddr2 channel 1 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_below_100Mhz_ch1_timings
+
+ str r5, [r4, #0xC] /* MMDC1_MDCFG0 */
+ str r7, [r4, #0x10] /* MMDC1_MDCFG1 */
+ str r9, [r4, #0x14] /* MMDC1_MDCFG2 */
+ str r10, [r4, #0x38] /* MMDC1_MDCFG3LP */
+
+skip_below_100Mhz_ch1_timings:
+
+ .endm
+
+ .macro restore_mmdc_settings_info
+ /* restore timing from mmdc_settings_info */
+ ldr r6, [r1, #0x0]
+ ldr r7, [r1, #0x4]
+1:
+ ldr r9, [r7], #0x4
+ ldr r10, [r7], #0x4
+ str r10, [r8, r9]
+ subs r6, r6, #0x1
+ bne 1b
+
+ /* Check if lpddr2 channel 1 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq 3f
+
+ ldr r6, [r1, #0x0]
+ ldr r7, [r1, #0x4]
+2:
+ ldr r9, [r7], #0x4
+ ldr r10, [r7], #0x4
+ str r10, [r4, r9]
+ subs r6, r6, #0x1
+ bne 2b
+3:
+
+ .endm
+
+ .macro mmdc_clk_lower_equal_100MHz
+
+ ldr r10, =100000000
+ cmp r0, r10
+ beq set_timmings_100MHz
+ set_timings_below_100MHz_operation
+ b common_to_lower_equal_100MHz
+
+set_timmings_100MHz:
+ restore_mmdc_settings_info
+ set_mmdc_misc_ralat_2_cycles
+
+common_to_lower_equal_100MHz:
+
+ /* if MMDC is not in 400MHz mode, skip double mu count */
+ ldr r5, [r1, #0x8]
+ ldr r6, =400000000
+ cmp r5, r6
+ bne skip_lower_force_measure_ch1
+
+ /*
+ * Prior to reducing the DDR frequency (at 528/400 MHz),
+ * read the Measure unit count bits (MU_UNIT_DEL_NUM)
+ */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r9, =0x3FF
+ and r6, r6, r9
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /*
+ * Bypass the automatic measure unit when below 100 MHz
+ * by setting the Measure unit bypass enable bit (MU_BYP_EN)
+ */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x400
+ str r6, [r8, r5]
+ /*
+ * Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r8, r5]
+ ldr r9, =0x3FF
+ bic r6, r6, r9
+ orr r6, r6, r7
+ str r6, [r8, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x800
+ str r6, [r8, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure:
+ ldr r6, [r8, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_lower_force_measure_ch1
+
+ ldr r5, =0x8B8
+ ldr r6, [r4, r5]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r9, =0x3FF
+ and r6, r6, r9
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /*
+ * Bypass the automatic measure unit when below 100 MHz
+ * by setting the Measure unit bypass enable bit (MU_BYP_EN)
+ */
+ ldr r6, [r4, r5]
+ orr r6, r6, #0x400
+ str r6, [r4, r5]
+ /*
+ * Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r4, r5]
+ ldr r9, =0x3FF
+ bic r6, r6, r9
+ orr r6, r6, r7
+ str r6, [r4, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r4, r5]
+ orr r6, r6, #0x800
+ str r6, [r4, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure_ch1:
+ ldr r6, [r4, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure_ch1
+
+skip_lower_force_measure_ch1:
+
+ .endm
+
+ .macro mmdc_clk_above_100MHz
+
+ restore_mmdc_settings_info
+
+ /* Make sure that the PHY measurement unit is NOT in bypass mode */
+ ldr r5, =0x8B8
+ ldr r6, [r8, r5]
+ bic r6, r6, #0x400
+ str r6, [r8, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r8, r5]
+ orr r6, r6, #0x800
+ str r6, [r8, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure1:
+ ldr r6, [r8, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_above_force_measure_ch1
+
+ ldr r5, =0x8B8
+ ldr r6, [r4, r5]
+ bic r6, r6, #0x400
+ str r6, [r4, r5]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r4, r5]
+ orr r6, r6, #0x800
+ str r6, [r4, r5]
+ /* Wait for FRC_MSR to clear. */
+force_measure1_ch1:
+ ldr r6, [r4, r5]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1_ch1
+
+skip_above_force_measure_ch1:
+
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ .endm
+
+/*
+ * mx6_lpddr2_freq_change
+ *
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ * r0 : DDR freq.
+ * r1 : mmdc_settings_info
+ */
+ .align 3
+ENTRY(mx6q_lpddr2_freq_change)
+mx6q_lpddr2_freq_change_start:
+ push {r2-r10}
+
+ /*
+ * Need to flush and disable L1 before
+ * disabling L2, we need data to
+ * coherent. Flushing L1 pushes
+ * everyhting to L2. We sync L2 later, but
+ * it can still have dirty lines.
+ * While exiting, we need to enable L2 first
+ * and then L1.
+ */
+ disable_l1_dcache
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Need to make sure the buffers in L2 are drained.
+ * Performing a sync operation does this.
+ */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+
+ /* Wait for background operations to complete. */
+wait_for_l2_to_idle:
+ ldr r6, [r7, #0x730]
+ cmp r6, #0x0
+ bne wait_for_l2_to_idle
+
+ mov r6, #0x0
+ str r6, [r7, #0x730]
+
+ /*
+ * The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+
+ /* Disable L2. */
+ str r6, [r7, #0x100]
+#endif
+
+ ldr r3, =IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR)
+ ldr r2, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r8, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+ ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P1_BASE_ADDR)
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* MMDC0_MDPDC disable power down timer */
+ ldr r6, [r8, #0x4]
+ bic r6, r6, #0xff00
+ str r6, [r8, #0x4]
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_psd_ch1
+
+ ldr r6, [r4, #0x404]
+ orr r6, r6, #0x01
+ str r6, [r4, #0x404]
+
+ ldr r6, [r4, #0x4]
+ bic r6, r6, #0xff00
+ str r6, [r4, #0x4]
+
+skip_psd_ch1:
+ /* Delay for a while */
+ ldr r10, =10
+delay1:
+ ldr r7, =0
+cont1:
+ ldr r6, [r8, r7]
+ add r7, r7, #4
+ cmp r7, #16
+ bne cont1
+ sub r10, r10, #1
+ cmp r10, #0
+ bgt delay1
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r8, #0x404]
+ orr r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_set_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r8, #0x410]
+ orr r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_sbs_ch1
+
+ ldr r6, [r4, #0x404]
+ orr r6, r6, #0x200000
+ str r6, [r4, #0x404]
+
+poll_dvfs_set_2:
+ ldr r6, [r4, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_2
+
+ ldr r6, [r4, #0x410]
+ orr r6, r6, #0x100
+ str r6, [r4, #0x410]
+
+skip_sbs_ch1:
+ ldr r10, =100000000
+ cmp r0, r10
+ bgt set_ddr_mu_above_100
+ mmdc_clk_lower_equal_100MHz
+
+set_ddr_mu_above_100:
+ ldr r10, =24000000
+ cmp r0, r10
+ beq set_to_24MHz
+
+ ldr r10, =100000000
+ cmp r0, r10
+ beq set_to_100MHz
+
+ ldr r10, =400000000
+ cmp r0, r10
+ switch_to_400MHz
+ b done
+
+set_to_24MHz:
+/*
+ switch_to_24MHZ_from_pll2
+*/
+ switch_to_24MHz
+ b done
+
+set_to_100MHz:
+ switch_to_100MHz
+
+done:
+
+ ldr r10,=100000000
+ cmp r0, r10
+ ble skip_mmdc_clk_check
+ mmdc_clk_above_100MHz
+
+skip_mmdc_clk_check:
+
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r8, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r8, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r8, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r8, #0x404]
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_enable_psd_ch1
+
+ ldr r6, [r4, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r4, #0x404]
+
+poll_dvfs_clear_2:
+ ldr r6, [r4, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_2
+
+ ldr r6, [r4, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r4, #0x404]
+
+skip_enable_psd_ch1:
+ ldr r10, =24000000
+ cmp r0, r10
+ beq skip_power_down
+
+ /* Enable MMDC power down timer. */
+ ldr r6, [r8, #0x4]
+ orr r6, r6, #0x5500
+ str r6, [r8, #0x4]
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_power_down
+
+ ldr r6, [r4, #0x4]
+ orr r6, r6, #0x5500
+ str r6, [r4, #0x4]
+
+skip_power_down:
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r8, #0x410]
+ bic r6, r6, #0x100
+ str r6, [r8, #0x410]
+
+ /* Check if lpddr2 channel 2 is enabled */
+ ldr r6, [r8, #0x18]
+ ands r6, r6, #(1 << 2)
+ beq skip_disable_sbs_ch1
+
+ ldr r6, [r4, #0x410]
+ bic r6, r6, #0x100
+ str r6, [r4, #0x410]
+
+skip_disable_sbs_ch1:
+#ifdef CONFIG_CACHE_L2X0
+ /* Enable L2. */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r6, =0x1
+ str r6, [r7, #0x100]
+#endif
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ pop {r2-r10}
+
+ /* Restore registers */
+ mov pc, lr
+
+ /*
+ * Add ltorg here to ensure that all
+ * literals are stored here and are
+ * within the text space.
+ */
+ .ltorg
+mx6q_lpddr2_freq_change_end:
diff --git a/arch/arm/mach-imx/lpddr2_freq_imx6sll.S b/arch/arm/mach-imx/lpddr2_freq_imx6sll.S
new file mode 100644
index 000000000000..c67d9e2b82ef
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6sll.S
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+#define CCM_CBCDR 0x14
+#define CCM_CBCMR 0x18
+#define CCM_CSCMR1 0x1c
+#define CCM_CDHIPR 0x48
+
+#define L2_CACHE_SYNC 0x730
+#define PL310_AUX_CTRL 0x104
+#define PL310_DCACHE_LOCKDOWN_BASE 0x900
+#define PL310_AUX_16WAY_BIT 0x10000
+#define PL310_LOCKDOWN_NBREGS 8
+#define PL310_LOCKDOWN_SZREG 4
+#define PL310_8WAYS_MASK 0x00FF
+#define PL310_16WAYS_UPPERMASK 0xFF00
+
+#define MMDC0_MDPDC 0x4
+#define MMDC0_MAPSR 0x404
+#define MMDC0_MADPCR0 0x410
+
+#define HIGH_BUS_MODE 0x0
+
+ .macro wait_for_ccm_handshake
+
+1:
+ ldr r8, [r2, #CCM_CDHIPR]
+ cmp r8, #0
+ bne 1b
+
+ .endm
+
+ .macro switch_to_24MHz
+
+ /* periph2_clk2 sel to OSC_CLK */
+ ldr r8, [r2, #CCM_CBCMR]
+ orr r8, r8, #(1 << 20)
+ str r8, [r2, #CCM_CBCMR]
+
+ /* periph2_clk2_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #0x7
+ str r8, [r2, #CCM_CBCDR]
+
+ /* periph2_clk sel to periph2_clk2 */
+ ldr r8, [r2, #CCM_CBCDR]
+ orr r8, r8, #(0x1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_100MHz
+
+ /* check whether periph2_clk is from top path */
+ ldr r8, [r2, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_100m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SLL, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_100m:
+
+ /* fabric_mmdc_podf to 3 so that mmdc is 400 / 4 = 100MHz */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ orr r8, r8, #(0x3 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_400MHz
+
+ /* check whether periph2_clk is from top path */
+ ldr r8, [r2, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_400m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SLL, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_400m:
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro mmdc_clk_lower_100MHz
+ /* if MMDC is not in 400MHz mode, skip double mu count */
+ cmp r1, #HIGH_BUS_MODE
+ bne 1f
+
+ /*
+ * Prior to reducing the DDR frequency (at 528/400 MHz),
+ * read the Measure unit count bits (MU_UNIT_DEL_NUM)
+ */
+ ldr r8, =0x8B8
+ ldr r6, [r5, r8]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r4, =0x3FF
+ and r6, r6, r4
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /*
+ * Bypass the automatic measure unit when below 100 MHz
+ * by setting the Measure unit bypass enable bit (MU_BYP_EN)
+ */
+ ldr r6, [r5, r8]
+ orr r6, r6, #0x400
+ str r6, [r5, r8]
+ /*
+ * Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r5, r8]
+ ldr r4, =0x3FF
+ bic r6, r6, r4
+ orr r6, r6, r7
+ str r6, [r5, r8]
+
+ /* For freq lower than 100MHz, need to set RALAT to 2 */
+ ldr r6, [r5, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x2 << 6)
+ str r6, [r5, #0x18]
+1:
+ .endm
+
+ .macro mmdc_clk_above_100MHz
+
+ /* Make sure that the PHY measurement unit is NOT in bypass mode */
+ ldr r8, =0x8B8
+ ldr r6, [r5, r8]
+ bic r6, r6, #0x400
+ str r6, [r5, r8]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r5, r8]
+ orr r6, r6, #0x800
+ str r6, [r5, r8]
+ /* Wait for FRC_MSR to clear. */
+force_measure1:
+ ldr r6, [r5, r8]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1
+
+ /* For freq higher than 100MHz, need to set RALAT to 5 */
+ ldr r6, [r5, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x5 << 6)
+ str r6, [r5, #0x18]
+
+ .endm
+
+ .align 3
+/*
+ * Below code can be used by i.MX6SLL when changing the
+ * frequency of MMDC. the MMDC is the same on these two SOCs.
+ */
+ENTRY(imx6sll_lpddr2_freq_change)
+ push {r2 - r8}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Need to make sure the buffers in L2 are drained.
+ * Performing a sync operation does this.
+ */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ mov r6, #0x0
+ str r6, [r7, #L2_CACHE_SYNC]
+
+ /*
+ * The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r3, #PL310_8WAYS_MASK
+ orrne r3, #PL310_16WAYS_UPPERMASK
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+ ldr r2, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r3, =IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR)
+ ldr r5, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ orr r6, r6, #0x1
+ str r6, [r5, #MMDC0_MAPSR]
+
+ /* Delay for a while */
+ ldr r8, =10
+delay:
+ ldr r7, =0
+cont:
+ ldr r6, [r5, r7]
+ add r7, r7, #4
+ cmp r7, #16
+ bne cont
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt delay
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ orr r6, r6, #0x200000
+ str r6, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_set_1:
+ ldr r6, [r5, #MMDC0_MAPSR]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r5, #MMDC0_MADPCR0]
+ orr r6, r6, #0x100
+ str r6, [r5, #MMDC0_MADPCR0]
+
+ ldr r6, =100000000
+ cmp r0, r6
+ bgt set_ddr_mu_above_100
+ mmdc_clk_lower_100MHz
+
+set_ddr_mu_above_100:
+ ldr r6, =24000000
+ cmp r0, r6
+ beq set_to_24MHz
+
+ ldr r6, =100000000
+ cmp r0, r6
+ beq set_to_100MHz
+
+ switch_to_400MHz
+
+ mmdc_clk_above_100MHz
+
+ b done
+
+set_to_24MHz:
+ switch_to_24MHz
+ b done
+set_to_100MHz:
+ switch_to_100MHz
+done:
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ bic r6, r6, #0x200000
+ str r6, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_clear_1:
+ ldr r6, [r5, #MMDC0_MAPSR]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ bic r6, r6, #0x1
+ str r6, [r5, #MMDC0_MAPSR]
+
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r5, #MMDC0_MADPCR0]
+ bic r6, r6, #0x100
+ str r6, [r5, #MMDC0_MADPCR0]
+
+ ldr r6, =0xa0000000
+ str r6, [r5, #0x83c]
+
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ mov r3, #0x00 /* 8 ways mask */
+ orrne r3, #0x0000 /* 16 ways mask */
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* Restore registers */
+ pop {r2 - r8}
+ mov pc, lr
diff --git a/arch/arm/mach-imx/lpddr2_freq_imx6sx.S b/arch/arm/mach-imx/lpddr2_freq_imx6sx.S
new file mode 100644
index 000000000000..ba3488cad9d4
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6sx.S
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+#define CCM_CBCDR 0x14
+#define CCM_CBCMR 0x18
+#define CCM_CSCMR1 0x1c
+#define CCM_CDHIPR 0x48
+
+#define L2_CACHE_SYNC 0x730
+#define PL310_AUX_CTRL 0x104
+#define PL310_DCACHE_LOCKDOWN_BASE 0x900
+#define PL310_AUX_16WAY_BIT 0x10000
+#define PL310_LOCKDOWN_NBREGS 8
+#define PL310_LOCKDOWN_SZREG 4
+#define PL310_8WAYS_MASK 0x00FF
+#define PL310_16WAYS_UPPERMASK 0xFF00
+
+#define MMDC0_MDPDC 0x4
+#define MMDC0_MAPSR 0x404
+#define MMDC0_MADPCR0 0x410
+
+#define HIGH_BUS_MODE 0x0
+
+ /* Check if the cpu is cortex-a7 */
+ .macro is_ca7
+
+ /* Read the primary cpu number is MPIDR */
+ mrc p15, 0, r6, c0, c0, 0
+ ldr r7, =0xfff0
+ and r6, r6, r7
+ ldr r7, =0xc070
+ cmp r6, r7
+
+ .endm
+
+ .macro wait_for_ccm_handshake
+
+1:
+ ldr r8, [r2, #CCM_CDHIPR]
+ cmp r8, #0
+ bne 1b
+
+ .endm
+
+ .macro switch_to_24MHz
+
+ /* periph2_clk2 sel to OSC_CLK */
+ ldr r8, [r2, #CCM_CBCMR]
+ orr r8, r8, #(1 << 20)
+ str r8, [r2, #CCM_CBCMR]
+
+ /* periph2_clk2_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #0x7
+ str r8, [r2, #CCM_CBCDR]
+
+ /* periph2_clk sel to periph2_clk2 */
+ ldr r8, [r2, #CCM_CBCDR]
+ orr r8, r8, #(0x1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_100MHz
+
+ /* check whether periph2_clk is from top path */
+ ldr r8, [r2, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_100m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_100m:
+
+ /* fabric_mmdc_podf to 3 so that mmdc is 400 / 4 = 100MHz */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ orr r8, r8, #(0x3 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro switch_to_400MHz
+
+ /* check whether periph2_clk is from top path */
+ ldr r8, [r2, #CCM_CBCDR]
+ ands r8, #(1 << 26)
+ beq skip_periph2_clk2_switch_400m
+
+ /* now switch periph2_clk back. */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(1 << 26)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_400m:
+
+ /* fabric_mmdc_podf to 0 */
+ ldr r8, [r2, #CCM_CBCDR]
+ bic r8, r8, #(0x7 << 3)
+ str r8, [r2, #CCM_CBCDR]
+
+ wait_for_ccm_handshake
+
+ .endm
+
+ .macro mmdc_clk_lower_100MHz
+ /* if MMDC is not in 400MHz mode, skip double mu count */
+ cmp r1, #HIGH_BUS_MODE
+ bne 1f
+
+ /*
+ * Prior to reducing the DDR frequency (at 528/400 MHz),
+ * read the Measure unit count bits (MU_UNIT_DEL_NUM)
+ */
+ ldr r8, =0x8B8
+ ldr r6, [r5, r8]
+ /* Original MU unit count */
+ mov r6, r6, LSR #16
+ ldr r4, =0x3FF
+ and r6, r6, r4
+ /* Original MU unit count * 2 */
+ mov r7, r6, LSL #1
+ /*
+ * Bypass the automatic measure unit when below 100 MHz
+ * by setting the Measure unit bypass enable bit (MU_BYP_EN)
+ */
+ ldr r6, [r5, r8]
+ orr r6, r6, #0x400
+ str r6, [r5, r8]
+ /*
+ * Double the measure count value read in step 1 and program it in the
+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
+ * Register for the reduced frequency operation below 100 MHz
+ */
+ ldr r6, [r5, r8]
+ ldr r4, =0x3FF
+ bic r6, r6, r4
+ orr r6, r6, r7
+ str r6, [r5, r8]
+
+ /* For freq lower than 100MHz, need to set RALAT to 2 */
+ ldr r6, [r5, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x2 << 6)
+ str r6, [r5, #0x18]
+1:
+ .endm
+
+ .macro mmdc_clk_above_100MHz
+
+ /* Make sure that the PHY measurement unit is NOT in bypass mode */
+ ldr r8, =0x8B8
+ ldr r6, [r5, r8]
+ bic r6, r6, #0x400
+ str r6, [r5, r8]
+ /* Now perform a Force Measurement. */
+ ldr r6, [r5, r8]
+ orr r6, r6, #0x800
+ str r6, [r5, r8]
+ /* Wait for FRC_MSR to clear. */
+force_measure1:
+ ldr r6, [r5, r8]
+ and r6, r6, #0x800
+ cmp r6, #0x0
+ bne force_measure1
+
+ /* For freq higher than 100MHz, need to set RALAT to 5 */
+ ldr r6, [r5, #0x18]
+ bic r6, r6, #(0x7 << 6)
+ orr r6, r6, #(0x5 << 6)
+ str r6, [r5, #0x18]
+
+ .endm
+
+ .align 3
+/*
+ * Below code can be used by i.MX6SX and i.MX6UL when changing the
+ * frequency of MMDC. the MMDC is the same on these two SOCs.
+ */
+ENTRY(imx6_up_lpddr2_freq_change)
+
+ push {r2 - r8}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ is_ca7
+ beq skip_disable_l2
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Need to make sure the buffers in L2 are drained.
+ * Performing a sync operation does this.
+ */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ mov r6, #0x0
+ str r6, [r7, #L2_CACHE_SYNC]
+
+ /*
+ * The second dsb might be needed to keep cache sync (device write)
+ * ordering with the memory accesses before it.
+ */
+ dsb
+ isb
+
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r3, #PL310_8WAYS_MASK
+ orrne r3, #PL310_16WAYS_UPPERMASK
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+skip_disable_l2:
+ ldr r2, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
+ ldr r3, =IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR)
+ ldr r5, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
+
+ /* Disable Automatic power savings. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ orr r6, r6, #0x1
+ str r6, [r5, #MMDC0_MAPSR]
+
+ /* MMDC0_MDPDC disable power down timer */
+ ldr r6, [r5, #MMDC0_MDPDC]
+ bic r6, r6, #0xff00
+ str r6, [r5, #MMDC0_MDPDC]
+
+ /* Delay for a while */
+ ldr r8, =10
+delay:
+ ldr r7, =0
+cont:
+ ldr r6, [r5, r7]
+ add r7, r7, #4
+ cmp r7, #16
+ bne cont
+ sub r8, r8, #1
+ cmp r8, #0
+ bgt delay
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ orr r6, r6, #0x200000
+ str r6, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_set_1:
+ ldr r6, [r5, #MMDC0_MAPSR]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ bne poll_dvfs_set_1
+
+ /* set SBS step-by-step mode */
+ ldr r6, [r5, #MMDC0_MADPCR0]
+ orr r6, r6, #0x100
+ str r6, [r5, #MMDC0_MADPCR0]
+
+ ldr r6, =100000000
+ cmp r0, r6
+ bgt set_ddr_mu_above_100
+ mmdc_clk_lower_100MHz
+
+set_ddr_mu_above_100:
+ ldr r6, =24000000
+ cmp r0, r6
+ beq set_to_24MHz
+
+ ldr r6, =100000000
+ cmp r0, r6
+ beq set_to_100MHz
+
+ switch_to_400MHz
+
+ mmdc_clk_above_100MHz
+
+ b done
+
+set_to_24MHz:
+ switch_to_24MHz
+ b done
+set_to_100MHz:
+ switch_to_100MHz
+done:
+ /* clear DVFS - exit from self refresh mode */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ bic r6, r6, #0x200000
+ str r6, [r5, #MMDC0_MAPSR]
+
+poll_dvfs_clear_1:
+ ldr r6, [r5, #MMDC0_MAPSR]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r5, #MMDC0_MAPSR]
+ bic r6, r6, #0x1
+ str r6, [r5, #MMDC0_MAPSR]
+
+ ldr r6, =24000000
+ cmp r0, r6
+ beq skip_power_down
+
+ /* Enable MMDC power down timer. */
+ ldr r6, [r5, #MMDC0_MDPDC]
+ orr r6, r6, #0x5500
+ str r6, [r5, #MMDC0_MDPDC]
+
+skip_power_down:
+ /* clear SBS - unblock DDR accesses */
+ ldr r6, [r5, #MMDC0_MADPCR0]
+ bic r6, r6, #0x100
+ str r6, [r5, #MMDC0_MADPCR0]
+
+ is_ca7
+ beq skip_enable_l2
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r3, [r7, #PL310_AUX_CTRL]
+ tst r3, #PL310_AUX_16WAY_BIT
+ mov r6, #PL310_LOCKDOWN_NBREGS
+ mov r3, #0x00 /* 8 ways mask */
+ orrne r3, #0x0000 /* 16 ways mask */
+ add r5, r7, #PL310_DCACHE_LOCKDOWN_BASE
+1: /* lock Dcache and Icache */
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ str r3, [r5], #PL310_LOCKDOWN_SZREG
+ subs r6, r6, #1
+ bne 1b
+#endif
+
+skip_enable_l2:
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* Restore registers */
+ pop {r2 - r8}
+ mov pc, lr
diff --git a/arch/arm/mach-imx/lpddr3_freq_imx.S b/arch/arm/mach-imx/lpddr3_freq_imx.S
new file mode 100644
index 000000000000..80fb1184fa54
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr3_freq_imx.S
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include "hardware.h"
+
+#define DDRC_MSTR 0x0
+#define DDRC_STAT 0x4
+#define DDRC_PWRCTL 0x30
+#define DDRC_RFSHTMG 0x64
+#define DDRC_DBG1 0x304
+#define DDRC_PSTAT 0x3fc
+#define DDRC_PCTRL_0 0x490
+#define DDRC_DFIMISC 0x1b0
+#define DDRC_DBGCAM 0x308
+#define DDRC_SWCTL 0x320
+#define DDRC_SWSTAT 0x324
+#define DDRPHY_LP_CON0 0x18
+#define IOMUXC_GPR8 0x20
+#define DDRPHY_PHY_CON1 0x4
+#define DDRPHY_MDLL_CON0 0xb0
+#define DDRPHY_MDLL_CON1 0xb4
+#define DDRPHY_OFFSETD_CON0 0x50
+#define DDRPHY_OFFSETR_CON0 0x20
+#define DDRPHY_OFFSETR_CON1 0x24
+#define DDRPHY_OFFSETR_CON2 0x28
+#define DDRPHY_OFFSETW_CON0 0x30
+#define DDRPHY_OFFSETW_CON1 0x34
+#define DDRPHY_OFFSETW_CON2 0x38
+#define DDRPHY_RFSHTMG 0x64
+#define DDRPHY_CA_WLDSKEW_CON0 0x6c
+#define DDRPHY_CA_DSKEW_CON0 0x7c
+#define DDRPHY_CA_DSKEW_CON1 0x80
+#define DDRPHY_CA_DSKEW_CON2 0x84
+
+#define ANADIG_DIGPROG 0x800
+
+ .align 3
+
+ .macro ddrc_prepare
+
+ /* disable port */
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_PCTRL_0]
+
+ /* wait port busy done */
+ ldr r6, =0x10001
+1:
+ ldr r7, [r4, #DDRC_PSTAT]
+ and r7, r7, r6
+ cmp r7, #0
+ bne 1b
+
+ ldr r7, =0x20
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x23
+2:
+ ldr r7, [r4, #DDRC_STAT]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 2b
+
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_DBG1]
+
+ ldr r6, =0x30000000
+3:
+ ldr r7, [r4, #DDRC_DBGCAM]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 3b
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_SWCTL]
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_DFIMISC]
+
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_SWCTL]
+
+ ldr r6, =0x1
+4:
+ ldr r7, [r4, #DDRC_SWSTAT]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 4b
+
+ .endm
+
+ .macro ddrc_done
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_PWRCTL]
+
+ ldr r6, =0x3
+5:
+ ldr r7, [r4, #DDRC_STAT]
+ and r7, r7, r6
+ cmp r7, r6
+ beq 5b
+
+ ldr r7, =0x0
+ str r7, [r4, #DDRC_DBG1]
+
+ ldr r7, =0x1
+ str r7, [r4, #DDRC_PCTRL_0]
+
+ /* enable auto self-refresh */
+ ldr r7, [r4, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r4, #DDRC_PWRCTL]
+
+ .endm
+
+ .macro switch_to_below_100m
+
+ /* LPDDR2 and LPDDR3 has different setting */
+ ldr r8, [r4, #DDRC_MSTR]
+ ands r8, r8, #0x4
+ bne 9f
+
+ /* LPDDR3 */
+ ldr r7, =0x00000100
+ str r7, [r5, #DDRPHY_PHY_CON1]
+ b 10f
+9:
+ /* LPDDR2 */
+ ldr r7, =0x10010100
+ str r7, [r5, #DDRPHY_PHY_CON1]
+10:
+ ldr r6, =24000000
+ cmp r0, r6
+ beq 16f
+
+ ldr r7, =0x0005000B
+ str r7, [r4, #DDRC_RFSHTMG]
+ b 6f
+16:
+ ldr r7, =0x00010003
+ str r7, [r4, #DDRC_RFSHTMG]
+
+ /* dram alt sel set to OSC */
+ ldr r7, =0x10000000
+ ldr r8, =0xa080
+ str r7, [r2, r8]
+ /* dram root set to from dram alt, div by 1 */
+ ldr r7, =0x11000000
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+ b 7f
+
+6:
+ /* dram alt sel set to pfd0_392m */
+ ldr r7, =0x15000000
+ ldr r8, =0xa080
+ str r7, [r2, r8]
+ /* dram root set to from dram alt, div by 4 */
+ ldr r7, =0x11000003
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+7:
+ ldr r7, =0x202ffd0
+ str r7, [r5, #DDRPHY_MDLL_CON0]
+
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r7, =0x7f7f7f7f
+ str r7, [r5, #DDRPHY_OFFSETR_CON0]
+ str r7, [r5, #DDRPHY_OFFSETR_CON1]
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETR_CON2]
+
+ ldr r7, =0x7f7f7f7f
+ str r7, [r5, #DDRPHY_OFFSETW_CON0]
+ str r7, [r5, #DDRPHY_OFFSETW_CON1]
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETW_CON2]
+
+ ldr r7, [r9, #ANADIG_DIGPROG]
+ and r7, r7, #0x11
+ cmp r7, #0x11
+ bne 11f
+
+ ldr r7, =0x0
+ str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
+ ldr r7, =0x60606060
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x00006060
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+ b 12f
+11:
+ ldr r7, =0x0
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+12:
+ ldr r7, =0x100007f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+ ldr r7, =0x7f
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ .endm
+
+ .macro switch_to_533m
+
+ ldr r7, =0x10210100
+ str r7, [r5, #DDRPHY_PHY_CON1]
+
+ ldr r7, =0x00200038
+ str r7, [r4, #DDRC_RFSHTMG]
+
+ /* dram root set to from dram main, div by 2 */
+ ldr r7, =0x10000001
+ ldr r8, =0x9880
+ str r7, [r2, r8]
+
+ ldr r7, =0x1010007e
+ str r7, [r5, #DDRPHY_MDLL_CON0]
+
+ ldr r7, =0x10000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_OFFSETR_CON0]
+ str r7, [r5, #DDRPHY_OFFSETR_CON1]
+ ldr r7, =0x8
+ str r7, [r5, #DDRPHY_OFFSETR_CON2]
+
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_OFFSETW_CON0]
+ str r7, [r5, #DDRPHY_OFFSETW_CON1]
+ ldr r7, =0x8
+ str r7, [r5, #DDRPHY_OFFSETW_CON2]
+
+ /* LPDDR2 and LPDDR3 has different setting */
+ ldr r8, [r4, #DDRC_MSTR]
+ ands r8, r8, #0x4
+ beq 15f
+
+ ldr r7, [r9, #ANADIG_DIGPROG]
+ and r7, r7, #0x11
+ cmp r7, #0x11
+ bne 14f
+
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x0a0a0808
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+ ldr r7, =0x0a0a0a0a
+ str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
+ b 14f
+15:
+ ldr r7, [r9, #ANADIG_DIGPROG]
+ and r7, r7, #0x11
+ cmp r7, #0x11
+ bne 13f
+
+ ldr r7, =0x1c1c1c1c
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x30301c1c
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+ ldr r7, =0x30303030
+ str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
+ b 14f
+13:
+ ldr r7, =0x08080808
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
+ ldr r7, =0x0808
+ str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
+14:
+ ldr r7, =0x11000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+ ldr r7, =0x10000008
+ str r7, [r5, #DDRPHY_OFFSETD_CON0]
+
+ ldr r6, =0x4
+8:
+ ldr r7, [r5, #DDRPHY_MDLL_CON1]
+ and r7, r7, r6
+ cmp r7, r6
+ bne 8b
+
+ .endm
+
+ENTRY(imx_lpddr3_freq_change)
+ push {r2 - r9}
+
+ /*
+ * To ensure no page table walks occur in DDR, we
+ * have a another page table stored in IRAM that only
+ * contains entries pointing to IRAM, AIPS1 and AIPS2.
+ * We need to set the TTBR1 to the new IRAM TLB.
+ * Do the following steps:
+ * 1. Flush the Branch Target Address Cache (BTAC)
+ * 2. Set TTBR1 to point to IRAM page table.
+ * 3. Disable page table walks in TTBR0 (PD0 = 1)
+ * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
+ * and 2-4G is translated by TTBR1.
+ */
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r7, c2, c0, 1
+
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ ldr r2, =IMX_IO_P2V(MX7D_CCM_BASE_ADDR)
+ ldr r3, =IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR)
+ ldr r4, =IMX_IO_P2V(MX7D_DDRC_BASE_ADDR)
+ ldr r5, =IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR)
+ ldr r9, =IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR)
+
+ ddrc_prepare
+
+ ldr r6, =100000000
+ cmp r0, r6
+ bgt set_to_533m
+
+set_to_below_100m:
+ switch_to_below_100m
+ b done
+
+set_to_533m:
+ switch_to_533m
+ b done
+
+done:
+ ddrc_done
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Restore the TTBCR */
+ dsb
+ isb
+
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ dsb
+ isb
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* Restore registers */
+ pop {r2 - r9}
+ mov pc, lr
+ENDPROC(imx_lpddr3_freq_change)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index edd26e0ffeec..730ce83eee0e 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -106,6 +106,18 @@ static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
+ /* Set RGMII IO voltage to 1.8V */
+ phy_write(dev, 0x1d, 0x1f);
+ phy_write(dev, 0x1e, 0x8);
+
+ /* disable phy AR8031 SmartEEE function. */
+ phy_write(dev, 0xd, 0x3);
+ phy_write(dev, 0xe, 0x805d);
+ phy_write(dev, 0xd, 0x4003);
+ val = phy_read(dev, 0xe);
+ val &= ~(0x1 << 8);
+ phy_write(dev, 0xe, val);
+
/* To enable AR8031 output a 125MHz clk from CLK_25M */
phy_write(dev, 0xd, 0x7);
phy_write(dev, 0xe, 0x8016);
@@ -223,6 +235,58 @@ put_node:
of_node_put(np);
}
+static void __init imx6q_csi_mux_init(void)
+{
+ /*
+ * MX6Q SabreSD board:
+ * IPU1 CSI0 connects to parallel interface.
+ * Set GPR1 bit 19 to 0x1.
+ *
+ * MX6DL SabreSD board:
+ * IPU1 CSI0 connects to parallel interface.
+ * Set GPR13 bit 0-2 to 0x4.
+ * IPU1 CSI1 connects to MIPI CSI2 virtual channel 1.
+ * Set GPR13 bit 3-5 to 0x1.
+ */
+ struct regmap *gpr;
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ if (of_machine_is_compatible("fsl,imx6q-sabresd") ||
+ of_machine_is_compatible("fsl,imx6q-sabreauto") ||
+ of_machine_is_compatible("fsl,imx6qp-sabresd") ||
+ of_machine_is_compatible("fsl,imx6qp-sabreauto"))
+ regmap_update_bits(gpr, IOMUXC_GPR1, 1 << 19, 1 << 19);
+ else if (of_machine_is_compatible("fsl,imx6dl-sabresd") ||
+ of_machine_is_compatible("fsl,imx6dl-sabreauto"))
+ regmap_update_bits(gpr, IOMUXC_GPR13, 0x3F, 0x0C);
+ } else {
+ pr_err("%s(): failed to find fsl,imx6q-iomux-gpr regmap\n",
+ __func__);
+ }
+}
+
+static void __init imx6q_enet_clk_sel(void)
+{
+ struct regmap *gpr;
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr))
+ regmap_update_bits(gpr, IOMUXC_GPR5,
+ IMX6Q_GPR5_ENET_TX_CLK_SEL, IMX6Q_GPR5_ENET_TX_CLK_SEL);
+ else
+ pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+}
+
+static inline void imx6q_enet_init(void)
+{
+ imx6_enet_mac_init("fsl,imx6q-fec", "fsl,imx6q-ocotp");
+ imx6q_enet_phy_init();
+ imx6q_1588_init();
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ imx6q_enet_clk_sel();
+}
+
static void __init imx6q_axi_init(void)
{
struct regmap *gpr;
@@ -260,7 +324,7 @@ static void __init imx6q_init_machine(void)
{
struct device *parent;
- if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0)
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
imx_print_silicon_rev("i.MX6QP", IMX_CHIP_REVISION_1_0);
else
imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
@@ -270,13 +334,12 @@ static void __init imx6q_init_machine(void)
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
- imx6q_enet_phy_init();
-
of_platform_default_populate(NULL, NULL, parent);
imx_anatop_init();
+ imx6q_enet_init();
+ imx6q_csi_mux_init();
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
- imx6q_1588_init();
imx6q_axi_init();
}
@@ -300,6 +363,8 @@ static void __init imx6q_map_io(void)
{
debug_ll_io_init();
imx_scu_map_io();
+ imx6_pm_map_io();
+ imx_busfreq_map_io();
}
static void __init imx6q_init_irq(void)
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index e00818abe54d..d1c6a9fa826a 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -16,7 +16,7 @@
#include "cpuidle.h"
#include "hardware.h"
-static void __init imx6sl_fec_init(void)
+static void __init imx6sl_fec_clk_init(void)
{
struct regmap *gpr;
@@ -32,6 +32,12 @@ static void __init imx6sl_fec_init(void)
}
}
+static inline void imx6sl_fec_init(void)
+{
+ imx6sl_fec_clk_init();
+ imx6_enet_mac_init("fsl,imx6sl-fec", "fsl,imx6sl-ocotp");
+}
+
static void __init imx6sl_init_late(void)
{
/* imx6sl reuses imx6q cpufreq driver */
@@ -41,7 +47,7 @@ static void __init imx6sl_init_late(void)
if (IS_ENABLED(CONFIG_SOC_IMX6SL) && cpu_is_imx6sl())
imx6sl_cpuidle_init();
else if (IS_ENABLED(CONFIG_SOC_IMX6SLL))
- imx6sx_cpuidle_init();
+ imx6sll_cpuidle_init();
}
static void __init imx6sl_init_machine(void)
@@ -54,6 +60,7 @@ static void __init imx6sl_init_machine(void)
of_platform_default_populate(NULL, NULL, parent);
+ imx_anatop_init();
if (cpu_is_imx6sl())
imx6sl_fec_init();
imx_anatop_init();
@@ -73,6 +80,14 @@ static void __init imx6sl_init_irq(void)
imx6_pm_ccm_init("fsl,imx6sll-ccm");
}
+static void __init imx6sl_map_io(void)
+{
+ imx6_pm_map_io();
+#ifdef CONFIG_CPU_FREQ
+ imx_busfreq_map_io();
+#endif
+}
+
static const char * const imx6sl_dt_compat[] __initconst = {
"fsl,imx6sl",
"fsl,imx6sll",
@@ -82,6 +97,7 @@ static const char * const imx6sl_dt_compat[] __initconst = {
DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
+ .map_io = imx6sl_map_io,
.init_irq = imx6sl_init_irq,
.init_machine = imx6sl_init_machine,
.init_late = imx6sl_init_late,
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index d5310bf307ff..118e9c9bb5a9 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -23,6 +23,14 @@ static int ar8031_phy_fixup(struct phy_device *dev)
phy_write(dev, 0x1d, 0x1f);
phy_write(dev, 0x1e, 0x8);
+ /* disable phy AR8031 SmartEEE function. */
+ phy_write(dev, 0xd, 0x3);
+ phy_write(dev, 0xe, 0x805d);
+ phy_write(dev, 0xd, 0x4003);
+ val = phy_read(dev, 0xe);
+ val &= ~(0x1 << 8);
+ phy_write(dev, 0xe, val);
+
/* introduce tx clock delay */
phy_write(dev, 0x1d, 0x5);
val = phy_read(dev, 0x1e);
@@ -57,6 +65,7 @@ static void __init imx6sx_enet_clk_sel(void)
static inline void imx6sx_enet_init(void)
{
+ imx6_enet_mac_init("fsl,imx6sx-fec", "fsl,imx6sx-ocotp");
imx6sx_enet_phy_init();
imx6sx_enet_clk_sel();
}
@@ -71,6 +80,7 @@ static void __init imx6sx_init_machine(void)
of_platform_default_populate(NULL, NULL, parent);
+ imx_anatop_init();
imx6sx_enet_init();
imx_anatop_init();
imx6sx_pm_init();
@@ -86,6 +96,13 @@ static void __init imx6sx_init_irq(void)
imx6_pm_ccm_init("fsl,imx6sx-ccm");
}
+static void __init imx6sx_map_io(void)
+{
+ debug_ll_io_init();
+ imx6_pm_map_io();
+ imx_busfreq_map_io();
+}
+
static void __init imx6sx_init_late(void)
{
imx6sx_cpuidle_init();
@@ -102,6 +119,7 @@ static const char * const imx6sx_dt_compat[] __initconst = {
DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
+ .map_io = imx6sx_map_io,
.init_irq = imx6sx_init_irq,
.init_machine = imx6sx_init_machine,
.dt_compat = imx6sx_dt_compat,
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index 311f5e4ff723..732f9419acd0 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -52,6 +52,7 @@ static inline void imx6ul_enet_init(void)
{
imx6ul_enet_clk_init();
imx6ul_enet_phy_init();
+ imx6_enet_mac_init("fsl,imx6ul-fec", "fsl,imx6ul-ocotp");
}
static void __init imx6ul_init_machine(void)
@@ -63,6 +64,7 @@ static void __init imx6ul_init_machine(void)
pr_warn("failed to initialize soc device\n");
of_platform_default_populate(NULL, NULL, parent);
+ imx_anatop_init();
imx6ul_enet_init();
imx_anatop_init();
imx6ul_pm_init();
@@ -78,12 +80,18 @@ static void __init imx6ul_init_irq(void)
static void __init imx6ul_init_late(void)
{
- imx6sx_cpuidle_init();
+ imx6ul_cpuidle_init();
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
}
+static void __init imx6ul_map_io(void)
+{
+ imx6_pm_map_io();
+ imx_busfreq_map_io();
+}
+
static const char * const imx6ul_dt_compat[] __initconst = {
"fsl,imx6ul",
"fsl,imx6ull",
@@ -91,6 +99,7 @@ static const char * const imx6ul_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
+ .map_io = imx6ul_map_io,
.init_irq = imx6ul_init_irq,
.init_machine = imx6ul_init_machine,
.init_late = imx6ul_init_late,
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index ebb27592a9f7..7ad5e6f240dd 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -13,6 +13,13 @@
#include <asm/mach/map.h>
#include "common.h"
+#include "cpuidle.h"
+
+static struct property device_disabled = {
+ .name = "status",
+ .length = sizeof("disabled"),
+ .value = "disabled",
+};
static int ar8031_phy_fixup(struct phy_device *dev)
{
@@ -57,6 +64,23 @@ static void __init imx7d_enet_phy_init(void)
}
}
+static void __init imx7d_enet_mdio_fixup(void)
+{
+ struct regmap *gpr;
+
+ /* The management data input/output (MDIO) bus where often high-speed,
+ * open-drain operation is required. i.MX7D TO1.0 ENET MDIO pin has no
+ * open drain as IC ticket number: TKT252980, i.MX7D TO1.1 fix the issue.
+ * GPR1[8:7] are reserved bits at TO1.0, there no need to add version check.
+ */
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");
+ if (!IS_ERR(gpr))
+ regmap_update_bits(gpr, IOMUXC_GPR0, IMX7D_GPR0_ENET_MDIO_OPEN_DRAIN_MASK,
+ IMX7D_GPR0_ENET_MDIO_OPEN_DRAIN_MASK);
+ else
+ pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n");
+}
+
static void __init imx7d_enet_clk_sel(void)
{
struct regmap *gpr;
@@ -72,10 +96,23 @@ static void __init imx7d_enet_clk_sel(void)
static inline void imx7d_enet_init(void)
{
+ imx6_enet_mac_init("fsl,imx7d-fec", "fsl,imx7d-ocotp");
+ imx7d_enet_mdio_fixup();
imx7d_enet_phy_init();
imx7d_enet_clk_sel();
}
+static inline void imx7d_disable_arm_arch_timer(void)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
+ if (node) {
+ pr_info("disable arm arch timer for nosmp!\n");
+ of_add_property(node, &device_disabled);
+ }
+}
+
static void __init imx7d_init_machine(void)
{
struct device *parent;
@@ -85,20 +122,35 @@ static void __init imx7d_init_machine(void)
pr_warn("failed to initialize soc device\n");
imx_anatop_init();
+ of_platform_default_populate(NULL, NULL, parent);
+ imx7d_pm_init();
+ imx_anatop_init();
imx7d_enet_init();
}
static void __init imx7d_init_late(void)
{
+ imx7d_cpuidle_init();
if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
}
static void __init imx7d_init_irq(void)
{
+ imx_gpcv2_check_dt();
imx_init_revision_from_anatop();
imx_src_init();
irqchip_init();
+#ifndef CONFIG_SMP
+ imx7d_disable_arm_arch_timer();
+#endif
+}
+
+static void __init imx7d_map_io(void)
+{
+ debug_ll_io_init();
+ imx7_pm_map_io();
+ imx_busfreq_map_io();
}
static const char *const imx7d_dt_compat[] __initconst = {
@@ -108,6 +160,8 @@ static const char *const imx7d_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
+ .map_io = imx7d_map_io,
+ .smp = smp_ops(imx_smp_ops),
.init_irq = imx7d_init_irq,
.init_machine = imx7d_init_machine,
.init_late = imx7d_init_late,
diff --git a/arch/arm/mach-imx/mach-imx7ulp.c b/arch/arm/mach-imx/mach-imx7ulp.c
index 11ac71aaf965..419c7905fe05 100644
--- a/arch/arm/mach-imx/mach-imx7ulp.c
+++ b/arch/arm/mach-imx/mach-imx7ulp.c
@@ -10,6 +10,7 @@
#include <linux/of_platform.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
#include "common.h"
#include "cpuidle.h"
@@ -17,6 +18,15 @@
#define SIM_JTAG_ID_REG 0x8c
+/* static IO mapping, and ioremap() could always share the same mapping. */
+static struct map_desc mx7ulp_io_desc[] __initdata = {
+ mx7ulp_aips_map_entry(1, MT_DEVICE),
+ mx7ulp_aips_map_entry(2, MT_DEVICE),
+ mx7ulp_aips_map_entry(3, MT_DEVICE),
+ mx7ulp_aips_map_entry(4, MT_DEVICE),
+ mx7ulp_aips_map_entry(5, MT_DEVICE),
+};
+
static void __init imx7ulp_set_revision(void)
{
struct regmap *sim;
@@ -65,12 +75,23 @@ static const char *const imx7ulp_dt_compat[] __initconst = {
NULL,
};
+static void __init imx7ulp_map_io(void)
+{
+ iotable_init(mx7ulp_io_desc, ARRAY_SIZE(mx7ulp_io_desc));
+ imx7ulp_pm_map_io();
+}
+
static void __init imx7ulp_init_late(void)
{
+ if (IS_ENABLED(CONFIG_ARM_IMX7ULP_CPUFREQ))
+ platform_device_register_simple("imx7ulp-cpufreq", -1, NULL, 0);
+
imx7ulp_cpuidle_init();
+ imx7ulp_enable_nmi();
}
DT_MACHINE_START(IMX7ulp, "Freescale i.MX7ULP (Device Tree)")
+ .map_io = imx7ulp_map_io,
.init_machine = imx7ulp_init_machine,
.dt_compat = imx7ulp_dt_compat,
.init_late = imx7ulp_init_late,
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index 0dfd0ae7a63d..8599936fc001 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -59,6 +59,7 @@
#define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
static int ddr_type;
+static int lpddr2_2ch_mode;
struct fsl_mmdc_devtype_data {
unsigned int flags;
@@ -575,6 +576,11 @@ int imx_mmdc_get_ddr_type(void)
return ddr_type;
}
+int imx_mmdc_get_lpddr2_2ch_mode(void)
+{
+ return lpddr2_2ch_mode;
+}
+
static struct platform_driver imx_mmdc_driver = {
.driver = {
.name = "imx-mmdc",
diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c
new file mode 100644
index 000000000000..1a250b07b256
--- /dev/null
+++ b/arch/arm/mach-imx/mu.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+ *
+ * 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/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+#include "common.h"
+#include "hardware.h"
+
+#define MU_ATR0_OFFSET 0x0
+#define MU_ARR0_OFFSET 0x10
+#define MU_ARR1_OFFSET 0x14
+#define MU_ASR 0x20
+#define MU_ACR 0x24
+#define MX7ULP_MU_TR0 0x20
+#define MX7ULP_MU_RR0 0x40
+#define MX7ULP_MU_RR1 0x44
+#define MX7ULP_MU_SR 0x60
+#define MX7ULP_MU_CR 0x64
+
+#define MU_LPM_HANDSHAKE_INDEX 0
+#define MU_RPMSG_HANDSHAKE_INDEX 1
+#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
+#define MU_LPM_M4_RELEASE_HIGH_BUS 0x2222BBBB
+#define MU_LPM_M4_WAKEUP_SRC_VAL 0x55555000
+#define MU_LPM_M4_WAKEUP_SRC_MASK 0xFFFFF000
+#define MU_LPM_M4_WAKEUP_IRQ_MASK 0xFF0
+#define MU_LPM_M4_WAKEUP_IRQ_SHIFT 0x4
+#define MU_LPM_M4_WAKEUP_ENABLE_MASK 0xF
+#define MU_LPM_M4_WAKEUP_ENABLE_SHIFT 0x0
+
+#define MU_LPM_M4_RUN_MODE 0x5A5A0001
+#define MU_LPM_M4_WAIT_MODE 0x5A5A0002
+#define MU_LPM_M4_STOP_MODE 0x5A5A0003
+
+#define MAX_NUM 10 /* enlarge it if overflow happen */
+
+static void __iomem *mu_base;
+static u32 m4_message[MAX_NUM];
+static u32 in_idx, out_idx;
+static struct delayed_work mu_work;
+static u32 m4_wake_irqs[4];
+static bool m4_freq_low;
+struct irq_domain *domain;
+static bool m4_in_stop;
+static struct clk *clk;
+static DEFINE_SPINLOCK(mu_lock);
+
+void imx_mu_set_m4_run_mode(void)
+{
+ m4_in_stop = false;
+}
+
+bool imx_mu_is_m4_in_stop(void)
+{
+ return m4_in_stop;
+}
+
+bool imx_mu_is_m4_in_low_freq(void)
+{
+ return m4_freq_low;
+}
+
+void imx_mu_enable_m4_irqs_in_gic(bool enable)
+{
+ int i, j;
+
+ for (i = 0; i < 4; i++) {
+ if (m4_wake_irqs[i] == 0)
+ continue;
+ for (j = 0; j < 32; j++) {
+ if (m4_wake_irqs[i] & (1 << j)) {
+ if (enable)
+ enable_irq(irq_find_mapping(
+ domain, i * 32 + j));
+ else
+ disable_irq(irq_find_mapping(
+ domain, i * 32 + j));
+ }
+ }
+ }
+}
+
+static irqreturn_t mcc_m4_dummy_isr(int irq, void *param)
+{
+ return IRQ_HANDLED;
+}
+
+static int imx_mu_send_message(unsigned int index, unsigned int data)
+{
+ u32 val, ep;
+ int i, te_flag = 0;
+ unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+ /* wait for transfer buffer empty, and no event pending */
+ do {
+ if (cpu_is_imx7ulp())
+ val = readl_relaxed(mu_base + MX7ULP_MU_SR);
+ else
+ val = readl_relaxed(mu_base + MU_ASR);
+ ep = val & BIT(4);
+ if (time_after(jiffies, timeout)) {
+ pr_err("Waiting MU transmit buffer empty timeout!\n");
+ return -EIO;
+ }
+ } while (((val & (1 << (20 + 3 - index))) == 0) || (ep == BIT(4)));
+
+ if (cpu_is_imx7ulp())
+ writel_relaxed(data, mu_base + index * 0x4 + MX7ULP_MU_TR0);
+ else
+ writel_relaxed(data, mu_base + index * 0x4 + MU_ATR0_OFFSET);
+
+ /*
+ * make a double check that TEn is not empty after write
+ */
+ if (cpu_is_imx7ulp())
+ val = readl_relaxed(mu_base + MX7ULP_MU_SR);
+ else
+ val = readl_relaxed(mu_base + MU_ASR);
+ ep = val & BIT(4);
+ if (((val & (1 << (20 + (3 - index)))) == 0) || (ep == BIT(4)))
+ return 0;
+ else
+ te_flag = 1;
+
+ /*
+ * Make sure that TEn flag is changed, after the ATRn is filled up.
+ */
+ for (i = 0; i < 100; i++) {
+ if (cpu_is_imx7ulp())
+ val = readl_relaxed(mu_base + MX7ULP_MU_SR);
+ else
+ val = readl_relaxed(mu_base + MU_ASR);
+ ep = val & BIT(4);
+ if (((val & (1 << (20 + 3 - index))) == 0) || (ep == BIT(4))) {
+ /*
+ * BUG here. TEn flag is changes, after the
+ * ATRn is filled with MSG for a while.
+ */
+ te_flag = 0;
+ break;
+ } else if (time_after(jiffies, timeout)) {
+ /* Can't see TEn 1->0, maybe already handled! */
+ te_flag = 1;
+ break;
+ }
+ }
+ if (te_flag == 0)
+ pr_info("BUG: TEn is not changed immediately"
+ "when ATRn is filled up.\n");
+
+ return 0;
+}
+
+static void mu_work_handler(struct work_struct *work)
+{
+ int ret;
+ u32 irq, enable, idx, mask, virq;
+ struct of_phandle_args args;
+ u32 message;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mu_lock, flags);
+ message = m4_message[out_idx % MAX_NUM];
+ spin_unlock_irqrestore(&mu_lock, flags);
+
+ pr_debug("receive M4 message 0x%x\n", message);
+
+ switch (message) {
+ case MU_LPM_M4_RUN_MODE:
+ case MU_LPM_M4_WAIT_MODE:
+ m4_in_stop = false;
+ break;
+ case MU_LPM_M4_STOP_MODE:
+ m4_in_stop = true;
+ break;
+ case MU_LPM_M4_REQUEST_HIGH_BUS:
+ request_bus_freq(BUS_FREQ_HIGH);
+#ifdef CONFIG_SOC_IMX6SX
+ if (cpu_is_imx6sx())
+ imx6sx_set_m4_highfreq(true);
+#endif
+ imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
+ MU_LPM_BUS_HIGH_READY_FOR_M4);
+ m4_freq_low = false;
+ break;
+ case MU_LPM_M4_RELEASE_HIGH_BUS:
+ release_bus_freq(BUS_FREQ_HIGH);
+#ifdef CONFIG_SOC_IMX6SX
+ if (cpu_is_imx6sx()) {
+ imx6sx_set_m4_highfreq(false);
+ imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
+ MU_LPM_M4_FREQ_CHANGE_READY);
+ }
+#endif
+ m4_freq_low = true;
+ break;
+ default:
+ if ((message & MU_LPM_M4_WAKEUP_SRC_MASK) ==
+ MU_LPM_M4_WAKEUP_SRC_VAL) {
+ irq = (message & MU_LPM_M4_WAKEUP_IRQ_MASK) >>
+ MU_LPM_M4_WAKEUP_IRQ_SHIFT;
+
+ enable = (message & MU_LPM_M4_WAKEUP_ENABLE_MASK) >>
+ MU_LPM_M4_WAKEUP_ENABLE_SHIFT;
+
+ /* to hwirq start from 0 */
+ irq -= 32;
+
+ idx = irq / 32;
+ mask = 1 << irq % 32;
+
+ args.np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-gpc");
+ args.args_count = 3;
+ args.args[0] = 0;
+ args.args[1] = irq;
+ args.args[2] = IRQ_TYPE_LEVEL_HIGH;
+
+ virq = irq_create_of_mapping(&args);
+
+ if (enable && can_request_irq(virq, 0)) {
+ ret = request_irq(virq, mcc_m4_dummy_isr,
+ IRQF_NO_SUSPEND, "imx-m4-dummy", NULL);
+ if (ret) {
+ pr_err("%s: register interrupt %d failed, rc %d\n",
+ __func__, virq, ret);
+ break;
+ }
+ disable_irq(virq);
+ m4_wake_irqs[idx] = m4_wake_irqs[idx] | mask;
+ }
+ imx_gpc_add_m4_wake_up_irq(irq, enable);
+ }
+ break;
+ }
+
+ spin_lock_irqsave(&mu_lock, flags);
+ m4_message[out_idx % MAX_NUM] = 0;
+ out_idx++;
+ spin_unlock_irqrestore(&mu_lock, flags);
+
+ /* enable RIE3 interrupt */
+ if (cpu_is_imx7ulp())
+ writel_relaxed(readl_relaxed(mu_base + MX7ULP_MU_CR) | BIT(27),
+ mu_base + MX7ULP_MU_CR);
+ else
+ writel_relaxed(readl_relaxed(mu_base + MU_ACR) | BIT(27),
+ mu_base + MU_ACR);
+}
+
+int imx_mu_lpm_ready(bool ready)
+{
+ u32 val;
+
+ if (cpu_is_imx7ulp()) {
+ val = readl_relaxed(mu_base + MX7ULP_MU_CR);
+ if (ready)
+ writel_relaxed(val | BIT(0), mu_base + MX7ULP_MU_CR);
+ else
+ writel_relaxed(val & ~BIT(0), mu_base + MX7ULP_MU_CR);
+ } else {
+ val = readl_relaxed(mu_base + MU_ACR);
+ if (ready)
+ writel_relaxed(val | BIT(0), mu_base + MU_ACR);
+ else
+ writel_relaxed(val & ~BIT(0), mu_base + MU_ACR);
+ }
+ return 0;
+}
+
+static irqreturn_t imx_mu_isr(int irq, void *param)
+{
+ u32 irqs;
+ unsigned long flags;
+
+ if (cpu_is_imx7ulp())
+ irqs = readl_relaxed(mu_base + MX7ULP_MU_SR);
+ else
+ irqs = readl_relaxed(mu_base + MU_ASR);
+
+ if (irqs & (1 << 27)) {
+ spin_lock_irqsave(&mu_lock, flags);
+ /* get message from receive buffer */
+ if (cpu_is_imx7ulp())
+ m4_message[in_idx % MAX_NUM] = readl_relaxed(mu_base +
+ MX7ULP_MU_RR0);
+ else
+ m4_message[in_idx % MAX_NUM] = readl_relaxed(mu_base +
+ MU_ARR0_OFFSET);
+ /* disable RIE3 interrupt */
+ if (cpu_is_imx7ulp())
+ writel_relaxed(readl_relaxed(mu_base + MX7ULP_MU_CR)
+ & (~BIT(27)), mu_base + MX7ULP_MU_CR);
+ else
+ writel_relaxed(readl_relaxed(mu_base + MU_ACR)
+ & (~BIT(27)), mu_base + MU_ACR);
+ in_idx++;
+ if (in_idx == out_idx) {
+ spin_unlock_irqrestore(&mu_lock, flags);
+ pr_err("MU overflow!\n");
+ return IRQ_HANDLED;
+ }
+ spin_unlock_irqrestore(&mu_lock, flags);
+
+ schedule_delayed_work(&mu_work, 0);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int imx_mu_probe(struct platform_device *pdev)
+{
+ int ret;
+ u32 irq;
+ struct device_node *np;
+ struct device *dev = &pdev->dev;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-mu-lp");
+ mu_base = of_iomap(np, 0);
+ WARN_ON(!mu_base);
+
+ ret = of_device_is_compatible(np, "fsl,imx7ulp-mu-lp");
+ if (ret)
+ irq = platform_get_irq(pdev, 1);
+ else
+ irq = platform_get_irq(pdev, 0);
+ ret = request_irq(irq, imx_mu_isr,
+ IRQF_NO_SUSPEND | IRQF_SHARED, "imx-mu-lp", dev);
+ if (ret) {
+ pr_err("%s: register interrupt %d failed, rc %d\n",
+ __func__, irq, ret);
+ return ret;
+ }
+
+ ret = of_device_is_compatible(np, "fsl,imx7d-mu-lp");
+ if (ret) {
+ clk = devm_clk_get(&pdev->dev, "mu");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev,
+ "mu clock source missing or invalid\n");
+ return PTR_ERR(clk);
+ } else {
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "unable to enable mu clock\n");
+ return ret;
+ }
+ }
+
+ /* MU always as a wakeup source for low power mode */
+ imx_gpcv2_add_m4_wake_up_irq(irq_to_desc(irq)->irq_data.hwirq,
+ true);
+ } else {
+ /* MU always as a wakeup source for low power mode */
+ imx_gpc_add_m4_wake_up_irq(irq_to_desc(irq)->irq_data.hwirq, true);
+ }
+
+ INIT_DELAYED_WORK(&mu_work, mu_work_handler);
+ /* bit0 of MX7ULP_MU_CR used to let m4 to know MU is ready now */
+ if (cpu_is_imx7ulp())
+ writel_relaxed(readl_relaxed(mu_base + MX7ULP_MU_CR) |
+ BIT(0) | BIT(26) | BIT(27), mu_base + MX7ULP_MU_CR);
+ else
+ writel_relaxed(readl_relaxed(mu_base + MU_ACR) |
+ BIT(26) | BIT(27), mu_base + MU_ACR);
+
+ pr_info("MU is ready for cross core communication!\n");
+
+ return 0;
+}
+
+static const struct of_device_id imx_mu_ids[] = {
+ { .compatible = "fsl,imx6sx-mu-lp" },
+ { .compatible = "fsl,imx7d-mu-lp" },
+ { .compatible = "fsl,imx7ulp-mu-lp" },
+ { }
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int mu_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int mu_resume(struct device *dev)
+{
+ if (!cpu_is_imx7ulp())
+ return 0;
+
+ writel_relaxed(readl_relaxed(mu_base + MX7ULP_MU_CR) |
+ BIT(0) | BIT(26) | BIT(27), mu_base + MX7ULP_MU_CR);
+
+ return 0;
+}
+#endif
+static const struct dev_pm_ops mu_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(mu_suspend, mu_resume)
+};
+
+static struct platform_driver imx_mu_driver = {
+ .driver = {
+ .name = "imx-mu-lp",
+ .owner = THIS_MODULE,
+ .pm = &mu_pm_ops,
+ .of_match_table = imx_mu_ids,
+ },
+ .probe = imx_mu_probe,
+};
+
+static int __init imx_mu_init(void)
+{
+ return platform_driver_register(&imx_mu_driver);
+}
+subsys_initcall(imx_mu_init);
diff --git a/arch/arm/mach-imx/mx6.h b/arch/arm/mach-imx/mx6.h
new file mode 100644
index 000000000000..06b8135a9954
--- /dev/null
+++ b/arch/arm/mach-imx/mx6.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2004-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * * 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.
+ * */
+
+#ifndef __ASM_ARCH_MXC_IOMAP_H__
+#define __ASM_ARCH_MXC_IOMAP_H__
+
+#define MX6Q_IO_P2V(x) IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x))
+
+#define MX6Q_L2_BASE_ADDR 0x00a02000
+#define MX6Q_L2_SIZE 0x1000
+#define MX6Q_IOMUXC_BASE_ADDR 0x020e0000
+#define MX6Q_IOMUXC_SIZE 0x4000
+#define MX6Q_SRC_BASE_ADDR 0x020d8000
+#define MX6Q_SRC_SIZE 0x4000
+#define MX6Q_CCM_BASE_ADDR 0x020c4000
+#define MX6Q_CCM_SIZE 0x4000
+#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
+#define MX6Q_ANATOP_SIZE 0x1000
+#define MX6Q_GPC_BASE_ADDR 0x020dc000
+#define MX6Q_GPC_SIZE 0x4000
+#define MX6Q_SEMA4_BASE_ADDR 0x02290000
+#define MX6Q_SEMA4_SIZE 0x4000
+#define MX6Q_MMDC_P0_BASE_ADDR 0x021b0000
+#define MX6Q_MMDC_P0_SIZE 0x4000
+#define MX6Q_MMDC_P1_BASE_ADDR 0x021b4000
+#define MX6Q_MMDC_P1_SIZE 0x4000
+#define MX6Q_AIPS1_BASE_ADDR 0x02000000
+#define MX6Q_AIPS1_SIZE 0x100000
+#define MX6Q_AIPS2_BASE_ADDR 0x02100000
+#define MX6Q_AIPS2_SIZE 0x100000
+#define MX6Q_AIPS3_BASE_ADDR 0x02200000
+#define MX6Q_AIPS3_SIZE 0x100000
+
+#define MX6SX_IRAM_TLB_BASE_ADDR 0x008f8000
+#define MX6Q_IRAM_TLB_BASE_ADDR 0x00900000
+#define MX6Q_IRAM_TLB_SIZE 0x4000
+#define TT_ATTRIB_NON_CACHEABLE_1M 0x802
+#define MX6_SUSPEND_IRAM_DATA_SIZE 256
+#define MX6SL_WFI_IRAM_DATA_SIZE 100
+
+#define MX6_SUSPEND_IRAM_ADDR_OFFSET 0
+#define MX6_CPUIDLE_IRAM_ADDR_OFFSET 0x1000
+#endif
diff --git a/arch/arm/mach-imx/mx7.h b/arch/arm/mach-imx/mx7.h
new file mode 100644
index 000000000000..afbeaef12d07
--- /dev/null
+++ b/arch/arm/mach-imx/mx7.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * * 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.
+ * */
+
+#ifndef __ASM_ARCH_MX7_IOMAP_H__
+#define __ASM_ARCH_MX7_IOMAP_H__
+
+#define MX7D_IO_P2V(x) IMX_IO_P2V(x)
+#define MX7D_IO_ADDRESS(x) IOMEM(MX7D_IO_P2V(x))
+
+#define MX7D_LPSR_BASE_ADDR 0x30270000
+#define MX7D_LPSR_SIZE 0x10000
+#define MX7D_CCM_BASE_ADDR 0x30380000
+#define MX7D_CCM_SIZE 0x10000
+#define MX7D_IOMUXC_BASE_ADDR 0x30330000
+#define MX7D_IOMUXC_SIZE 0x10000
+#define MX7D_IOMUXC_GPR_BASE_ADDR 0x30340000
+#define MX7D_IOMUXC_GPR_SIZE 0x10000
+#define MX7D_ANATOP_BASE_ADDR 0x30360000
+#define MX7D_ANATOP_SIZE 0x10000
+#define MX7D_SNVS_BASE_ADDR 0x30370000
+#define MX7D_SNVS_SIZE 0x10000
+#define MX7D_GPC_BASE_ADDR 0x303a0000
+#define MX7D_GPC_SIZE 0x10000
+#define MX7D_SRC_BASE_ADDR 0x30390000
+#define MX7D_SRC_SIZE 0x10000
+#define MX7D_DDRC_BASE_ADDR 0x307a0000
+#define MX7D_DDRC_SIZE 0x10000
+#define MX7D_DDRC_PHY_BASE_ADDR 0x30790000
+#define MX7D_DDRC_PHY_SIZE 0x10000
+#define MX7D_AIPS1_BASE_ADDR 0x30000000
+#define MX7D_AIPS1_SIZE 0x400000
+#define MX7D_AIPS2_BASE_ADDR 0x30400000
+#define MX7D_AIPS2_SIZE 0x400000
+#define MX7D_AIPS3_BASE_ADDR 0x30900000
+#define MX7D_AIPS3_SIZE 0x300000
+#define MX7D_GIC_BASE_ADDR 0x31000000
+#define MX7D_GIC_SIZE 0x100000
+
+#define TT_ATTRIB_NON_CACHEABLE_1M 0x802
+#define MX7_IRAM_TLB_SIZE 0x4000
+#define MX7_SUSPEND_OCRAM_SIZE 0x1000
+#define MX7_CPUIDLE_OCRAM_ADDR_OFFSET 0x1000
+#define MX7_CPUIDLE_OCRAM_SIZE 0x1000
+#define MX7_BUSFREQ_OCRAM_ADDR_OFFSET 0x2000
+#define MX7_BUSFREQ_OCRAM_SIZE 0x1000
+
+#endif
diff --git a/arch/arm/mach-imx/mx7ulp.h b/arch/arm/mach-imx/mx7ulp.h
new file mode 100644
index 000000000000..35638dfea68b
--- /dev/null
+++ b/arch/arm/mach-imx/mx7ulp.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright NXP 2017.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MX7ULP_IOMAP_H__
+#define __ASM_ARCH_MX7ULP_IOMAP_H__
+
+#define MX7ULP_IO_P2V(x) IMX_IO_P2V(x)
+#define MX7ULP_IO_ADDRESS(x) IOMEM(MX7ULP_IO_P2V(x))
+
+#define MX7ULP_AIPS1_BASE_ADDR 0x40000000
+#define MX7ULP_AIPS1_SIZE 0x100000
+#define MX7ULP_AIPS2_BASE_ADDR 0x40300000
+#define MX7ULP_AIPS2_SIZE 0x100000
+#define MX7ULP_AIPS3_BASE_ADDR 0x40400000
+#define MX7ULP_AIPS3_SIZE 0x100000
+#define MX7ULP_AIPS4_BASE_ADDR 0x40a00000
+#define MX7ULP_AIPS4_SIZE 0x100000
+#define MX7ULP_AIPS5_BASE_ADDR 0x41000000
+#define MX7ULP_AIPS5_SIZE 0x100000
+#define MX7ULP_GPIOC_BASE_ADDR 0x400f0000
+#define MX7ULP_GPIOC_SIZE 0x1000
+#define MX7ULP_PCC3_BASE_ADDR 0x40b30000
+#define MX7ULP_PCC3_SIZE 0x1000
+#define MX7ULP_SCG1_BASE_ADDR 0x403e0000
+#define MX7ULP_SCG1_SIZE 0x1000
+#define MX7ULP_PCC2_BASE_ADDR 0x403f0000
+#define MX7ULP_PCC2_SIZE 0x1000
+#define MX7ULP_SIM_BASE_ADDR 0x410a3000
+#define MX7ULP_SIM_SIZE 0x1000
+#define MX7ULP_PMC1_BASE_ADDR 0x40400000
+#define MX7ULP_PMC1_SIZE 0x1000
+#define MX7ULP_SMC1_BASE_ADDR 0x40410000
+#define MX7ULP_SMC1_SIZE 0x1000
+#define MX7ULP_MMDC_BASE_ADDR 0x40ab0000
+#define MX7ULP_MMDC_SIZE 0x1000
+#define MX7ULP_IOMUXC1_BASE_ADDR 0x40ac0000
+#define MX7ULP_IOMUXC1_BASE__SIZE 0x1000
+#define MX7ULP_MMDC_IO_BASE_ADDR 0x40ad0000
+#define MX7ULP_MMDC_IO_SIZE 0x1000
+
+/* below is just used for static mapping of the AIPSx's memory region */
+#define MX7ULP_AIPS_VIRT_BASE(x) (0xf4000000 + ((x) * SZ_1M))
+
+#define mx7ulp_aips_map_entry(index, _type) { \
+ .virtual = MX7ULP_AIPS_VIRT_BASE(index), \
+ .pfn = __phys_to_pfn(MX7ULP_AIPS ## index ## _BASE_ADDR), \
+ .length = SZ_1M, \
+ .type = _type, \
+}
+
+#define TT_ATTRIB_NON_CACHEABLE_1M 0x802
+#define MX7ULP_IRAM_TLB_SIZE 0x4000
+#define MX7ULP_SUSPEND_OCRAM_SIZE 0x1000
+
+#endif
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 2bfd2d59b4a6..c311f9d48de2 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -33,7 +33,13 @@
#define MXC_CPU_IMX7D 0x72
#define MXC_CPU_IMX7ULP 0xff
+#define IMX_DDR_TYPE_DDR3 0
#define IMX_DDR_TYPE_LPDDR2 1
+#define IMX_DDR_TYPE_LPDDR3 2
+#define IMX_MMDC_DDR_TYPE_LPDDR3 3
+
+#define IMX_LPDDR2_1CH_MODE 0
+#define IMX_LPDDR2_2CH_MODE 1
#ifndef __ASSEMBLY__
extern unsigned int __mxc_cpu_type;
@@ -85,11 +91,28 @@ static inline bool cpu_is_imx6q(void)
return __mxc_cpu_type == MXC_CPU_IMX6Q;
}
+static inline bool cpu_is_imx6(void)
+{
+ return __mxc_cpu_type == MXC_CPU_IMX6Q ||
+ __mxc_cpu_type == MXC_CPU_IMX6DL ||
+ __mxc_cpu_type == MXC_CPU_IMX6SL ||
+ __mxc_cpu_type == MXC_CPU_IMX6SX ||
+ __mxc_cpu_type == MXC_CPU_IMX6UL ||
+ __mxc_cpu_type == MXC_CPU_IMX6ULL ||
+ __mxc_cpu_type == MXC_CPU_IMX6SLL ||
+ __mxc_cpu_type == MXC_CPU_IMX6ULZ;
+}
+
static inline bool cpu_is_imx7d(void)
{
return __mxc_cpu_type == MXC_CPU_IMX7D;
}
+static inline bool cpu_is_imx7ulp(void)
+{
+ return __mxc_cpu_type == MXC_CPU_IMX7ULP;
+}
+
struct cpu_op {
u32 cpu_rate;
};
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 2aa26928221d..90dccaa66c89 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -18,7 +18,7 @@
#include "hardware.h"
u32 g_diag_reg;
-static void __iomem *scu_base;
+void __iomem *scu_base;
static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -47,15 +47,39 @@ static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
return 0;
}
+#define MXC_ARCH_CA7 0xc07
+static unsigned long __mxc_arch_type;
+
+static inline bool arm_is_ca7(void)
+{
+ return __mxc_arch_type == MXC_ARCH_CA7;
+}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
static void __init imx_smp_init_cpus(void)
{
+ unsigned long arch_type;
int i, ncores;
- ncores = scu_get_core_count(scu_base);
+ asm volatile(
+ ".align 4\n"
+ "mrc p15, 0, %0, c0, c0, 0\n"
+ : "=r" (arch_type)
+ );
+ /* MIDR[15:4] defines ARCH type */
+ __mxc_arch_type = (arch_type >> 4) & 0xfff;
+
+ if (arm_is_ca7()) {
+ unsigned long val;
+
+ /* CA7 core number, [25:24] of CP15 L2CTLR */
+ asm volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ ncores = ((val >> 24) & 0x3) + 1;
+ } else {
+ ncores = scu_get_core_count(scu_base);
+ }
for (i = ncores; i < NR_CPUS; i++)
set_cpu_possible(i, false);
@@ -63,11 +87,15 @@ static void __init imx_smp_init_cpus(void)
void imx_smp_prepare(void)
{
+ if (arm_is_ca7())
+ return;
scu_enable(scu_base);
}
static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
{
+ if (arm_is_ca7())
+ return;
imx_smp_prepare();
/*
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index baf3b47601af..9f44f0fa121f 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright 2011-2014 Freescale Semiconductor, Inc.
+ * Copyright 2011-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*/
@@ -13,15 +13,21 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_fdt.h>
#include <linux/of_platform.h>
+#include <linux/psci.h>
#include <linux/regmap.h>
+#include <linux/slab.h>
#include <linux/suspend.h>
#include <asm/cacheflush.h>
#include <asm/fncpy.h>
+#include <asm/mach/map.h>
#include <asm/proc-fns.h>
#include <asm/suspend.h>
#include <asm/tlb.h>
+#include <uapi/linux/psci.h>
+
#include "common.h"
#include "hardware.h"
@@ -54,13 +60,215 @@
#define CGPR 0x64
#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
+#define CCGR4 0x78
+#define CCGR6 0x80
#define MX6Q_SUSPEND_OCRAM_SIZE 0x1000
-#define MX6_MAX_MMDC_IO_NUM 33
+#define MX6_MAX_MMDC_IO_NUM 36
+#define MX6_MAX_MMDC_NUM 36
+
+#define ROMC_ROMPATCH0D 0xf0
+#define ROMC_ROMPATCHCNTL 0xf4
+#define ROMC_ROMPATCHENL 0xfc
+#define ROMC_ROMPATCH0A 0x100
+#define BM_ROMPATCHCNTL_0D (0x1 << 0)
+#define BM_ROMPATCHCNTL_DIS (0x1 << 29)
+#define BM_ROMPATCHENL_0D (0x1 << 0)
+#define ROM_ADDR_FOR_INTERNAL_RAM_BASE 0x10d7c
+
+#define UART_UCR1 0x80
+#define UART_UCR2 0x84
+#define UART_UCR3 0x88
+#define UART_UCR4 0x8c
+#define UART_UFCR 0x90
+#define UART_UESC 0x9c
+#define UART_UTIM 0xa0
+#define UART_UBIR 0xa4
+#define UART_UBMR 0xa8
+#define UART_UBRC 0xac
+#define UART_UTS 0xb4
+
+#define IOMUXC_GPR5_CLOCK_AFCG_X_BYPASS_MASK 0xf800
+
+extern unsigned long iram_tlb_base_addr;
+extern unsigned long iram_tlb_phys_addr;
+
+/* QSPI register layout */
+#define QSPI_MCR 0x00
+#define QSPI_IPCR 0x08
+#define QSPI_BUF0CR 0x10
+#define QSPI_BUF1CR 0x14
+#define QSPI_BUF2CR 0x18
+#define QSPI_BUF3CR 0x1c
+#define QSPI_BFGENCR 0x20
+#define QSPI_BUF0IND 0x30
+#define QSPI_BUF1IND 0x34
+#define QSPI_BUF2IND 0x38
+#define QSPI_SFAR 0x100
+#define QSPI_SMPR 0x108
+#define QSPI_RBSR 0x10c
+#define QSPI_RBCT 0x110
+#define QSPI_TBSR 0x150
+#define QSPI_TBDR 0x154
+#define QSPI_SFA1AD 0x180
+#define QSPI_SFA2AD 0x184
+#define QSPI_SFB1AD 0x188
+#define QSPI_SFB2AD 0x18c
+#define QSPI_RBDR_BASE 0x200
+#define QSPI_LUTKEY 0x300
+#define QSPI_LCKCR 0x304
+#define QSPI_LUT_BASE 0x310
+
+#define QSPI_RBDR_(x) (QSPI_RBDR_BASE + (x) * 4)
+#define QSPI_LUT(x) (QSPI_LUT_BASE + (x) * 4)
+
+#define QSPI_LUTKEY_VALUE 0x5AF05AF0
+#define QSPI_LCKER_LOCK 0x1
+#define QSPI_LCKER_UNLOCK 0x2
+
+enum qspi_regs_valuetype {
+ QSPI_PREDEFINED,
+ QSPI_RETRIEVED,
+};
+
+struct qspi_regs {
+ int offset;
+ unsigned int value;
+ enum qspi_regs_valuetype valuetype;
+};
+struct qspi_regs qspi_regs_imx6sx[] = {
+ {QSPI_IPCR, 0, QSPI_RETRIEVED},
+ {QSPI_BUF0CR, 0, QSPI_RETRIEVED},
+ {QSPI_BUF1CR, 0, QSPI_RETRIEVED},
+ {QSPI_BUF2CR, 0, QSPI_RETRIEVED},
+ {QSPI_BUF3CR, 0, QSPI_RETRIEVED},
+ {QSPI_BFGENCR, 0, QSPI_RETRIEVED},
+ {QSPI_BUF0IND, 0, QSPI_RETRIEVED},
+ {QSPI_BUF1IND, 0, QSPI_RETRIEVED},
+ {QSPI_BUF2IND, 0, QSPI_RETRIEVED},
+ {QSPI_SFAR, 0, QSPI_RETRIEVED},
+ {QSPI_SMPR, 0, QSPI_RETRIEVED},
+ {QSPI_RBSR, 0, QSPI_RETRIEVED},
+ {QSPI_RBCT, 0, QSPI_RETRIEVED},
+ {QSPI_TBSR, 0, QSPI_RETRIEVED},
+ {QSPI_TBDR, 0, QSPI_RETRIEVED},
+ {QSPI_SFA1AD, 0, QSPI_RETRIEVED},
+ {QSPI_SFA2AD, 0, QSPI_RETRIEVED},
+ {QSPI_SFB1AD, 0, QSPI_RETRIEVED},
+ {QSPI_SFB2AD, 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(0), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(1), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(2), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(3), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(4), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(5), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(6), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(7), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(8), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(9), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(10), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(11), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(12), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(13), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(14), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(15), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(16), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(17), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(18), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(19), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(20), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(21), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(22), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(23), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(24), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(25), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(26), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(27), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(28), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(29), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(30), 0, QSPI_RETRIEVED},
+ {QSPI_RBDR_(31), 0, QSPI_RETRIEVED},
+ {QSPI_LUTKEY, QSPI_LUTKEY_VALUE, QSPI_PREDEFINED},
+ {QSPI_LCKCR, QSPI_LCKER_UNLOCK, QSPI_PREDEFINED},
+ {QSPI_LUT(0), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(1), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(2), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(3), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(4), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(5), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(6), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(7), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(8), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(9), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(10), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(11), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(12), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(13), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(14), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(15), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(16), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(17), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(18), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(19), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(20), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(21), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(22), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(23), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(24), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(25), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(26), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(27), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(28), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(29), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(30), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(31), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(32), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(33), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(34), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(35), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(36), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(37), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(38), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(39), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(40), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(41), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(42), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(43), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(44), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(45), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(46), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(47), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(48), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(49), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(50), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(51), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(52), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(53), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(54), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(55), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(56), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(57), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(58), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(59), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(60), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(61), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(62), 0, QSPI_RETRIEVED},
+ {QSPI_LUT(63), 0, QSPI_RETRIEVED},
+ {QSPI_LUTKEY, QSPI_LUTKEY_VALUE, QSPI_PREDEFINED},
+ {QSPI_LCKCR, QSPI_LCKER_LOCK, QSPI_PREDEFINED},
+ {QSPI_MCR, 0, QSPI_RETRIEVED},
+};
+
+static unsigned int *ocram_saved_in_ddr;
+static void __iomem *ocram_base;
+static void __iomem *console_base;
+static void __iomem *qspi_base;
+static unsigned int ocram_size;
static void __iomem *ccm_base;
static void __iomem *suspend_ocram_base;
static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
+struct regmap *romcp;
/*
* suspend ocram space layout:
@@ -90,6 +298,8 @@ struct imx6_pm_socdata {
const char *pl310_compat;
const u32 mmdc_io_num;
const u32 *mmdc_io_offset;
+ const u32 mmdc_num;
+ const u32 *mmdc_offset;
};
static const u32 imx6q_mmdc_io_offset[] __initconst = {
@@ -104,6 +314,18 @@ static const u32 imx6q_mmdc_io_offset[] __initconst = {
0x74c, /* GPR_ADDS */
};
+static const u32 imx6q_mmdc_io_lpddr2_offset[] __initconst = {
+ 0x5ac, 0x5b4, 0x528, 0x520, /* DQM0 ~ DQM3 */
+ 0x514, 0x510, 0x5bc, 0x5c4, /* DQM4 ~ DQM7 */
+ 0x784, 0x788, 0x794, 0x79c, /* GPR_B0DS ~ GPR_B3DS */
+ 0x7a0, 0x7a4, 0x7a8, 0x748, /* GPR_B4DS ~ GPR_B7DS */
+ 0x56c, 0x578, 0x588, 0x594, /* CAS, RAS, SDCLK_0, SDCLK_1 */
+ 0x5a8, 0x5b0, 0x524, 0x51c, /* SDQS0 ~ SDQS3 */
+ 0x518, 0x50c, 0x5b8, 0x5c0, /* SDQS4 ~ SDQS7 */
+ 0x59c, 0x5a0, 0x750, 0x774, /* SODT0, SODT1, MODE_CTL, MODE */
+ 0x74c, 0x590, 0x598, 0x57c, /* GRP_ADDS, SDCKE0, SDCKE1, RESET */
+};
+
static const u32 imx6dl_mmdc_io_offset[] __initconst = {
0x470, 0x474, 0x478, 0x47c, /* DQM0 ~ DQM3 */
0x480, 0x484, 0x488, 0x48c, /* DQM4 ~ DQM7 */
@@ -124,11 +346,25 @@ static const u32 imx6sl_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x320, /* SDCKE0, SDCKE1, RESET */
};
-static const u32 imx6sll_mmdc_io_offset[] __initconst = {
- 0x294, 0x298, 0x29c, 0x2a0, /* DQM0 ~ DQM3 */
- 0x544, 0x54c, 0x554, 0x558, /* GPR_B0DS ~ GPR_B3DS */
- 0x530, 0x540, 0x2ac, 0x52c, /* MODE_CTL, MODE, SDCLK_0, GPR_ADDDS */
- 0x2a4, 0x2a8, /* SDCKE0, SDCKE1*/
+static const u32 imx6sx_mmdc_io_lpddr2_offset[] __initconst = {
+ 0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
+ 0x300, 0x2fc, 0x32c, 0x5f4, /* CAS, RAS, SDCLK_0, GPR_ADDS */
+ 0x60c, 0x610, 0x61c, 0x620, /* GPR_B0DS ~ GPR_B3DS */
+ 0x310, 0x314, 0x5f8, 0x608, /* SODT0, SODT1, MODE_CTL, MODE */
+ 0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
+ 0x324, 0x328, 0x340, /* DRAM_SDCKE0 ~ 1, DRAM_RESET */
+};
+
+static const u32 imx6sx_mmdc_lpddr2_offset[] __initconst = {
+ 0x01c, 0x85c, 0x800, 0x890,
+ 0x8b8, 0x81c, 0x820, 0x824,
+ 0x828, 0x82c, 0x830, 0x834,
+ 0x838, 0x848, 0x850, 0x8c0,
+ 0x83c, 0x840, 0x8b8, 0x00c,
+ 0x004, 0x010, 0x014, 0x018,
+ 0x02c, 0x030, 0x038, 0x008,
+ 0x040, 0x000, 0x020, 0x818,
+ 0x800, 0x004, 0x01c,
};
static const u32 imx6sx_mmdc_io_offset[] __initconst = {
@@ -139,6 +375,16 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
};
+static const u32 imx6sx_mmdc_offset[] __initconst = {
+ 0x800, 0x80c, 0x810, 0x83c,
+ 0x840, 0x848, 0x850, 0x81c,
+ 0x820, 0x824, 0x828, 0x8b8,
+ 0x004, 0x008, 0x00c, 0x010,
+ 0x014, 0x018, 0x01c, 0x02c,
+ 0x030, 0x040, 0x000, 0x01c,
+ 0x020, 0x818, 0x01c,
+};
+
static const u32 imx6ul_mmdc_io_offset[] __initconst = {
0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
@@ -146,6 +392,53 @@ static const u32 imx6ul_mmdc_io_offset[] __initconst = {
0x494, 0x4b0, /* MODE_CTL, MODE, */
};
+static const u32 imx6ul_mmdc_offset[] __initconst = {
+ 0x01c, 0x800, 0x80c, 0x83c,
+ 0x848, 0x850, 0x81c, 0x820,
+ 0x82c, 0x830, 0x8c0, 0x8b8,
+ 0x004, 0x008, 0x00c, 0x010,
+ 0x014, 0x018, 0x01c, 0x02c,
+ 0x030, 0x040, 0x000, 0x01c,
+ 0x020, 0x818, 0x01c,
+};
+
+static const u32 imx6ul_mmdc_io_lpddr2_offset[] __initconst = {
+ 0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
+ 0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
+ 0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */
+ 0x494, 0x4b0, 0x274, 0x278, /* MODE_CTL, MODE, SDCKE0, SDCKE1 */
+ 0x288, /* DRAM_RESET */
+};
+
+static const u32 imx6ul_mmdc_lpddr2_offset[] __initconst = {
+ 0x01c, 0x85c, 0x800, 0x890,
+ 0x8b8, 0x81c, 0x820, 0x82c,
+ 0x830, 0x83c, 0x848, 0x850,
+ 0x8c0, 0x8b8, 0x004, 0x008,
+ 0x00c, 0x010, 0x038, 0x014,
+ 0x018, 0x01c, 0x02c, 0x030,
+ 0x040, 0x000, 0x020, 0x818,
+ 0x800, 0x004, 0x01c,
+};
+
+static const u32 imx6sll_mmdc_io_offset[] __initconst = {
+ 0x294, 0x298, 0x29c, 0x2a0, /* DQM0 ~ DQM3 */
+ 0x544, 0x54c, 0x554, 0x558, /* GPR_B0DS ~ GPR_B3DS */
+ 0x530, 0x540, 0x2ac, 0x52c, /* MODE_CTL, MODE, SDCLK_0, GPR_ADDDS */
+ 0x2a4, 0x2a8, /* SDCKE0, SDCKE1*/
+};
+
+static const u32 imx6sll_mmdc_lpddr3_offset[] __initconst = {
+ 0x01c, 0x85c, 0x800, 0x890,
+ 0x8b8, 0x81c, 0x820, 0x82c,
+ 0x830, 0x83c, 0x848, 0x850,
+ 0x8c0, 0x8b8, 0x004, 0x008,
+ 0x00c, 0x010, 0x038, 0x014,
+ 0x018, 0x01c, 0x02c, 0x030,
+ 0x040, 0x000, 0x020, 0x818,
+ 0x800, 0x004, 0x01c,
+};
+
static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
@@ -154,6 +447,19 @@ static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
.mmdc_io_offset = imx6q_mmdc_io_offset,
+ .mmdc_num = 0,
+ .mmdc_offset = NULL,
+};
+
+static const struct imx6_pm_socdata imx6q_lpddr2_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx6q-mmdc",
+ .src_compat = "fsl,imx6q-src",
+ .iomuxc_compat = "fsl,imx6q-iomuxc",
+ .gpc_compat = "fsl,imx6q-gpc",
+ .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_lpddr2_offset),
+ .mmdc_io_offset = imx6q_mmdc_io_lpddr2_offset,
+ .mmdc_num = 0,
+ .mmdc_offset = NULL,
};
static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
@@ -164,6 +470,8 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
.mmdc_io_offset = imx6dl_mmdc_io_offset,
+ .mmdc_num = 0,
+ .mmdc_offset = NULL,
};
static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
@@ -174,16 +482,8 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
.mmdc_io_offset = imx6sl_mmdc_io_offset,
-};
-
-static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
- .mmdc_compat = "fsl,imx6sll-mmdc",
- .src_compat = "fsl,imx6sll-src",
- .iomuxc_compat = "fsl,imx6sll-iomuxc",
- .gpc_compat = "fsl,imx6sll-gpc",
- .pl310_compat = "arm,pl310-cache",
- .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
- .mmdc_io_offset = imx6sll_mmdc_io_offset,
+ .mmdc_num = 0,
+ .mmdc_offset = NULL,
};
static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
@@ -194,6 +494,19 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
.mmdc_io_offset = imx6sx_mmdc_io_offset,
+ .mmdc_num = ARRAY_SIZE(imx6sx_mmdc_offset),
+ .mmdc_offset = imx6sx_mmdc_offset,
+};
+
+static const struct imx6_pm_socdata imx6sx_lpddr2_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx6sx-mmdc",
+ .src_compat = "fsl,imx6sx-src",
+ .iomuxc_compat = "fsl,imx6sx-iomuxc",
+ .gpc_compat = "fsl,imx6sx-gpc",
+ .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_lpddr2_offset),
+ .mmdc_io_offset = imx6sx_mmdc_io_lpddr2_offset,
+ .mmdc_num = ARRAY_SIZE(imx6sx_mmdc_lpddr2_offset),
+ .mmdc_offset = imx6sx_mmdc_lpddr2_offset,
};
static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
@@ -204,6 +517,61 @@ static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
.pl310_compat = NULL,
.mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
.mmdc_io_offset = imx6ul_mmdc_io_offset,
+ .mmdc_num = ARRAY_SIZE(imx6ul_mmdc_offset),
+ .mmdc_offset = imx6ul_mmdc_offset,
+};
+
+static const struct imx6_pm_socdata imx6ul_lpddr2_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx6ul-mmdc",
+ .src_compat = "fsl,imx6ul-src",
+ .iomuxc_compat = "fsl,imx6ul-iomuxc",
+ .gpc_compat = "fsl,imx6ul-gpc",
+ .mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_lpddr2_offset),
+ .mmdc_io_offset = imx6ul_mmdc_io_lpddr2_offset,
+ .mmdc_num = ARRAY_SIZE(imx6ul_mmdc_lpddr2_offset),
+ .mmdc_offset = imx6ul_mmdc_lpddr2_offset,
+};
+
+static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx6sll-mmdc",
+ .src_compat = "fsl,imx6sll-src",
+ .iomuxc_compat = "fsl,imx6sll-iomuxc",
+ .gpc_compat = "fsl,imx6sll-gpc",
+ .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
+ .mmdc_io_offset = imx6sll_mmdc_io_offset,
+ .mmdc_num = ARRAY_SIZE(imx6sll_mmdc_lpddr3_offset),
+ .mmdc_offset = imx6sll_mmdc_lpddr3_offset,
+};
+
+static struct map_desc iram_tlb_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_1M,
+ .type = MT_MEMORY_RWX_NONCACHED,
+};
+
+/*
+ * AIPS1 and AIPS2 is not used, because it will trigger a BUG_ON if
+ * lowlevel debug and earlyprintk are configured.
+ *
+ * it is because there is a vm conflict because UART1 is mapped early if
+ * AIPS1 is mapped using 1M size.
+ *
+ * Thus no use AIPS1 and AIPS2 to avoid kernel BUG_ON.
+ */
+static struct map_desc imx6_pm_io_desc[] __initdata = {
+ imx_map_entry(MX6Q, MMDC_P0, MT_DEVICE),
+ imx_map_entry(MX6Q, MMDC_P1, MT_DEVICE),
+ imx_map_entry(MX6Q, SRC, MT_DEVICE),
+ imx_map_entry(MX6Q, IOMUXC, MT_DEVICE),
+ imx_map_entry(MX6Q, CCM, MT_DEVICE),
+ imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+ imx_map_entry(MX6Q, GPC, MT_DEVICE),
+ imx_map_entry(MX6Q, L2, MT_DEVICE),
+};
+
+static const char * const low_power_ocram_match[] __initconst = {
+ "fsl,lpm-sram",
+ NULL
};
/*
@@ -218,14 +586,19 @@ struct imx6_cpu_pm_info {
phys_addr_t resume_addr; /* The physical resume address for asm code */
u32 ddr_type;
u32 pm_info_size; /* Size of pm_info. */
- struct imx6_pm_base mmdc_base;
+ struct imx6_pm_base mmdc0_base;
+ struct imx6_pm_base mmdc1_base;
struct imx6_pm_base src_base;
struct imx6_pm_base iomuxc_base;
struct imx6_pm_base ccm_base;
struct imx6_pm_base gpc_base;
struct imx6_pm_base l2_base;
+ struct imx6_pm_base anatop_base;
+ u32 ttbr1; /* Store TTBR1 */
u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
- u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+ u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][3]; /* To save offset, value, low power settings */
+ u32 mmdc_num; /* Number of MMDC registers which need saved/restored. */
+ u32 mmdc_val[MX6_MAX_MMDC_NUM][2];
} __aligned(8);
void imx6_set_int_mem_clk_lpm(bool enable)
@@ -304,11 +677,18 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= 0x2 << BP_CLPCR_LPM;
val &= ~BM_CLPCR_VSTBY;
val &= ~BM_CLPCR_SBYOS;
- if (cpu_is_imx6sl())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6sll())
val |= BM_CLPCR_BYPASS_PMIC_READY;
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
- cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
+ cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ else if (cpu_is_imx6q() &&
+ imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2 &&
+ imx_mmdc_get_lpddr2_2ch_mode() == IMX_LPDDR2_2CH_MODE) {
+ /* keep handshake enabled for lpddr2 2ch-mode */
+ val &= ~BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ val &= ~BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ }
else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
@@ -322,11 +702,18 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= 0x3 << BP_CLPCR_STBY_COUNT;
val |= BM_CLPCR_VSTBY;
val |= BM_CLPCR_SBYOS;
- if (cpu_is_imx6sl() || cpu_is_imx6sx())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6sll())
val |= BM_CLPCR_BYPASS_PMIC_READY;
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
- cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
+ cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ else if (cpu_is_imx6q() &&
+ imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2 &&
+ imx_mmdc_get_lpddr2_2ch_mode() == IMX_LPDDR2_2CH_MODE) {
+ /* keep handshake enabled for lpddr2 2ch-mode */
+ val &= ~BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ val &= ~BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ }
else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
@@ -357,8 +744,18 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
return 0;
}
+#define MX6Q_SUSPEND_PARAM \
+ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
static int imx6q_suspend_finish(unsigned long val)
{
+ if (psci_ops.cpu_suspend) {
+ return psci_ops.cpu_suspend(MX6Q_SUSPEND_PARAM,
+ __pa(cpu_resume));
+ }
+
if (!imx6_suspend_in_ocram_fn) {
cpu_do_idle();
} else {
@@ -377,19 +774,104 @@ static int imx6q_suspend_finish(unsigned long val)
return 0;
}
+static void imx6_console_save(unsigned int *regs)
+{
+ if (!console_base)
+ return;
+
+ regs[0] = readl_relaxed(console_base + UART_UCR1);
+ regs[1] = readl_relaxed(console_base + UART_UCR2);
+ regs[2] = readl_relaxed(console_base + UART_UCR3);
+ regs[3] = readl_relaxed(console_base + UART_UCR4);
+ regs[4] = readl_relaxed(console_base + UART_UFCR);
+ regs[5] = readl_relaxed(console_base + UART_UESC);
+ regs[6] = readl_relaxed(console_base + UART_UTIM);
+ regs[7] = readl_relaxed(console_base + UART_UBIR);
+ regs[8] = readl_relaxed(console_base + UART_UBMR);
+ regs[9] = readl_relaxed(console_base + UART_UTS);
+}
+
+static void imx6_console_restore(unsigned int *regs)
+{
+ if (!console_base)
+ return;
+
+ writel_relaxed(regs[4], console_base + UART_UFCR);
+ writel_relaxed(regs[5], console_base + UART_UESC);
+ writel_relaxed(regs[6], console_base + UART_UTIM);
+ writel_relaxed(regs[7], console_base + UART_UBIR);
+ writel_relaxed(regs[8], console_base + UART_UBMR);
+ writel_relaxed(regs[9], console_base + UART_UTS);
+ writel_relaxed(regs[0], console_base + UART_UCR1);
+ writel_relaxed(regs[1] | 0x1, console_base + UART_UCR2);
+ writel_relaxed(regs[2], console_base + UART_UCR3);
+ writel_relaxed(regs[3], console_base + UART_UCR4);
+}
+
+static void imx6_qspi_save(struct qspi_regs *pregs, int reg_num)
+{
+ int i;
+
+ if (!qspi_base)
+ return;
+
+ for (i = 0; i < reg_num; i++) {
+ if (QSPI_RETRIEVED == pregs[i].valuetype)
+ pregs[i].value = readl_relaxed(qspi_base +
+ pregs[i].offset);
+ }
+}
+
+static void imx6_qspi_restore(struct qspi_regs *pregs, int reg_num)
+{
+ int i;
+
+ if (!qspi_base)
+ return;
+
+ for (i = 0; i < reg_num; i++)
+ writel_relaxed(pregs[i].value, qspi_base + pregs[i].offset);
+}
+
static int imx6q_pm_enter(suspend_state_t state)
{
+ unsigned int console_saved_reg[10] = {0};
+ static unsigned int ccm_ccgr4, ccm_ccgr6;
+
+#ifdef CONFIG_SOC_IMX6SX
+ if (imx_src_is_m4_enabled()) {
+ if (imx_gpc_is_m4_sleeping() && imx_mu_is_m4_in_low_freq()) {
+ imx_gpc_hold_m4_in_sleep();
+ imx_mu_enable_m4_irqs_in_gic(true);
+ } else {
+ pr_info("M4 is busy, enter WAIT mode instead of STOP!\n");
+ imx6_set_lpm(WAIT_UNCLOCKED);
+ imx6_set_int_mem_clk_lpm(true);
+ imx_gpc_pre_suspend(false);
+ /* Zzz ... */
+ cpu_do_idle();
+ imx_gpc_post_resume();
+ imx6_set_lpm(WAIT_CLOCKED);
+
+ return 0;
+ }
+ }
+#endif
switch (state) {
case PM_SUSPEND_STANDBY:
imx6_set_lpm(STOP_POWER_ON);
imx6_set_int_mem_clk_lpm(true);
imx_gpc_pre_suspend(false);
+#ifdef CONFIG_SOC_IMX6SL
if (cpu_is_imx6sl())
imx6sl_set_wait_clk(true);
+#endif
/* Zzz ... */
cpu_do_idle();
+#ifdef CONFIG_SOC_IMX6SL
if (cpu_is_imx6sl())
imx6sl_set_wait_clk(false);
+#endif
imx_gpc_post_resume();
imx6_set_lpm(WAIT_CLOCKED);
break;
@@ -405,8 +887,50 @@ static int imx6q_pm_enter(suspend_state_t state)
imx6_enable_rbc(true);
imx_gpc_pre_suspend(true);
imx_anatop_pre_suspend();
+ if ((cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) &&
+ imx_gpc_is_mf_mix_off())
+ imx6_console_save(console_saved_reg);
+ if (cpu_is_imx6sx() && imx_gpc_is_mf_mix_off()) {
+ ccm_ccgr4 = readl_relaxed(ccm_base + CCGR4);
+ ccm_ccgr6 = readl_relaxed(ccm_base + CCGR6);
+ /*
+ * i.MX6SX RDC needs PCIe and eim clk to be enabled
+ * if Mega/Fast off, it is better to check cpu type
+ * and whether Mega/Fast is off in this suspend flow,
+ * but we need to add cpu type check for 3 places which
+ * will increase code size, so here we just do it
+ * for all cases, as when STOP mode is entered, CCM
+ * hardware will gate all clocks, so it will NOT impact
+ * any function or power.
+ */
+ writel_relaxed(ccm_ccgr4 | (0x3 << 0), ccm_base +
+ CCGR4);
+ writel_relaxed(ccm_ccgr6 | (0x3 << 10), ccm_base +
+ CCGR6);
+ memcpy(ocram_saved_in_ddr, ocram_base, ocram_size);
+ imx6_console_save(console_saved_reg);
+ if (imx_src_is_m4_enabled())
+ imx6_qspi_save(qspi_regs_imx6sx,
+ sizeof(qspi_regs_imx6sx) /
+ sizeof(struct qspi_regs));
+ }
+
/* Zzz ... */
cpu_suspend(0, imx6q_suspend_finish);
+
+ if (cpu_is_imx6sx() && imx_gpc_is_mf_mix_off()) {
+ writel_relaxed(ccm_ccgr4, ccm_base + CCGR4);
+ writel_relaxed(ccm_ccgr6, ccm_base + CCGR6);
+ memcpy(ocram_base, ocram_saved_in_ddr, ocram_size);
+ imx6_console_restore(console_saved_reg);
+ if (imx_src_is_m4_enabled())
+ imx6_qspi_restore(qspi_regs_imx6sx,
+ sizeof(qspi_regs_imx6sx) /
+ sizeof(struct qspi_regs));
+ }
+ if ((cpu_is_imx6ull() || cpu_is_imx6ulz() || cpu_is_imx6sll()) &&
+ imx_gpc_is_mf_mix_off())
+ imx6_console_restore(console_saved_reg);
if (cpu_is_imx6q() || cpu_is_imx6dl())
imx_smp_prepare();
imx_anatop_post_resume();
@@ -420,6 +944,13 @@ static int imx6q_pm_enter(suspend_state_t state)
return -EINVAL;
}
+#ifdef CONFIG_SOC_IMX6SX
+ if (imx_src_is_m4_enabled()) {
+ imx_mu_enable_m4_irqs_in_gic(false);
+ imx_gpc_release_m4_in_sleep();
+ }
+#endif
+
return 0;
}
@@ -433,41 +964,114 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
.valid = imx6q_pm_valid,
};
-static int __init imx6_pm_get_base(struct imx6_pm_base *base,
- const char *compat)
+static int __init imx6_dt_find_lpsram(unsigned long node, const char *uname,
+ int depth, void *data)
{
- struct device_node *node;
- struct resource res;
- int ret = 0;
+ unsigned long lpram_addr;
+ const __be32 *prop = of_get_flat_dt_prop(node, "reg", NULL);
- node = of_find_compatible_node(NULL, NULL, compat);
- if (!node)
- return -ENODEV;
+ if (of_flat_dt_match(node, low_power_ocram_match)) {
+ if (!prop)
+ return -EINVAL;
- ret = of_address_to_resource(node, 0, &res);
- if (ret)
- goto put_node;
+ lpram_addr = be32_to_cpup(prop);
- base->pbase = res.start;
- base->vbase = ioremap(res.start, resource_size(&res));
- if (!base->vbase)
- ret = -ENOMEM;
+ /* We need to create a 1M page table entry. */
+ iram_tlb_io_desc.virtual = IMX_IO_P2V(lpram_addr & 0xFFF00000);
+ iram_tlb_io_desc.pfn = __phys_to_pfn(lpram_addr & 0xFFF00000);
+ iram_tlb_phys_addr = lpram_addr;
+ iram_tlb_base_addr = IMX_IO_P2V(lpram_addr);
-put_node:
- of_node_put(node);
- return ret;
+ iotable_init(&iram_tlb_io_desc, 1);
+ }
+
+ return 0;
+}
+
+void __init imx6_pm_map_io(void)
+{
+ unsigned long i;
+
+ iotable_init(imx6_pm_io_desc, ARRAY_SIZE(imx6_pm_io_desc));
+
+ /*
+ * Get the address of IRAM or OCRAM to be used by the low
+ * power code from the device tree.
+ */
+ WARN_ON(of_scan_flat_dt(imx6_dt_find_lpsram, NULL));
+
+ /*
+ * We moved suspend/resume and lowpower idle to TEE,
+ * But busfreq now still in Linux, this table is still needed
+ * If we later decide to move busfreq to TEE, we could drop this.
+ */
+ /* Return if no IRAM space is allocated for suspend/resume code. */
+ if (!iram_tlb_base_addr) {
+ pr_warn("No IRAM/OCRAM memory allocated for suspend/resume \
+ code. Please ensure device tree has an entry for \
+ fsl,lpm-sram.\n");
+ return;
+ }
+
+ /* Set all entries to 0. */
+ memset((void *)iram_tlb_base_addr, 0, MX6Q_IRAM_TLB_SIZE);
+
+ /*
+ * Make sure the IRAM virtual address has a mapping in the IRAM
+ * page table.
+ *
+ * Only use the top 11 bits [31-20] when storing the physical
+ * address in the page table as only these bits are required
+ * for 1M mapping.
+ */
+ i = ((iram_tlb_base_addr >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (iram_tlb_phys_addr & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
+
+ /*
+ * Make sure the AIPS1 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ i = ((IMX_IO_P2V(MX6Q_AIPS1_BASE_ADDR) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (MX6Q_AIPS1_BASE_ADDR & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+
+ /*
+ * Make sure the AIPS2 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ i = ((IMX_IO_P2V(MX6Q_AIPS2_BASE_ADDR) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (MX6Q_AIPS2_BASE_ADDR & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+
+ /*
+ * Make sure the AIPS3 virtual address has a mapping
+ * in the IRAM page table.
+ */
+ i = ((IMX_IO_P2V(MX6Q_AIPS3_BASE_ADDR) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (MX6Q_AIPS3_BASE_ADDR & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+
+ /*
+ * Make sure the L2 controller virtual address has a mapping
+ * in the IRAM page table.
+ */
+ i = ((IMX_IO_P2V(MX6Q_L2_BASE_ADDR) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + i) =
+ (MX6Q_L2_BASE_ADDR & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
}
static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
{
- phys_addr_t ocram_pbase;
struct device_node *node;
- struct platform_device *pdev;
struct imx6_cpu_pm_info *pm_info;
- struct gen_pool *ocram_pool;
- unsigned long ocram_base;
+ unsigned long iram_paddr;
int i, ret = 0;
const u32 *mmdc_offset_array;
+ const u32 *mmdc_io_offset_array;
suspend_set_ops(&imx6q_pm_ops);
@@ -476,41 +1080,30 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
return -EINVAL;
}
- node = of_find_compatible_node(NULL, NULL, "mmio-sram");
- if (!node) {
- pr_warn("%s: failed to find ocram node!\n", __func__);
- return -ENODEV;
+ if (psci_ops.cpu_suspend) {
+ /* TODO: seems not needed */
+ /* of_node_put(node); */
+ return ret;
}
- pdev = of_find_device_by_node(node);
- if (!pdev) {
- pr_warn("%s: failed to find ocram device!\n", __func__);
- ret = -ENODEV;
- goto put_node;
- }
-
- ocram_pool = gen_pool_get(&pdev->dev, NULL);
- if (!ocram_pool) {
- pr_warn("%s: ocram pool unavailable!\n", __func__);
- ret = -ENODEV;
- goto put_device;
- }
-
- ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
- if (!ocram_base) {
- pr_warn("%s: unable to alloc ocram!\n", __func__);
- ret = -ENOMEM;
- goto put_device;
- }
+ /*
+ * 16KB is allocated for IRAM TLB, but only up 8k is for kernel TLB,
+ * The lower 8K is not used, so use the lower 8K for IRAM code and
+ * pm_info.
+ *
+ */
+ iram_paddr = iram_tlb_phys_addr + MX6_SUSPEND_IRAM_ADDR_OFFSET;
- ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
+ /* Make sure iram_paddr is 8 byte aligned. */
+ if ((uintptr_t)(iram_paddr) & (FNCPY_ALIGN - 1))
+ iram_paddr += FNCPY_ALIGN - iram_paddr % (FNCPY_ALIGN);
- suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
- MX6Q_SUSPEND_OCRAM_SIZE, false);
+ /* Get the virtual address of the suspend code. */
+ suspend_ocram_base = (void *)IMX_IO_P2V(iram_paddr);
memset(suspend_ocram_base, 0, sizeof(*pm_info));
pm_info = suspend_ocram_base;
- pm_info->pbase = ocram_pbase;
+ pm_info->pbase = iram_paddr;
pm_info->resume_addr = __pa_symbol(v7_cpu_resume);
pm_info->pm_info_size = sizeof(*pm_info);
@@ -518,70 +1111,127 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
* ccm physical address is not used by asm code currently,
* so get ccm virtual address directly.
*/
- pm_info->ccm_base.vbase = ccm_base;
+ pm_info->ccm_base.pbase = MX6Q_CCM_BASE_ADDR;
+ pm_info->ccm_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_CCM_BASE_ADDR);
- ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
- if (ret) {
- pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
- goto put_device;
- }
+ pm_info->mmdc0_base.pbase = MX6Q_MMDC_P0_BASE_ADDR;
+ pm_info->mmdc0_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR);
- ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
- if (ret) {
- pr_warn("%s: failed to get src base %d!\n", __func__, ret);
- goto src_map_failed;
- }
+ pm_info->mmdc1_base.pbase = MX6Q_MMDC_P1_BASE_ADDR;
+ pm_info->mmdc1_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_MMDC_P1_BASE_ADDR);
- ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat);
- if (ret) {
- pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret);
- goto iomuxc_map_failed;
- }
+ pm_info->src_base.pbase = MX6Q_SRC_BASE_ADDR;
+ pm_info->src_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_SRC_BASE_ADDR);
- ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
- if (ret) {
- pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
- goto gpc_map_failed;
- }
+ pm_info->iomuxc_base.pbase = MX6Q_IOMUXC_BASE_ADDR;
+ pm_info->iomuxc_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR);
- if (socdata->pl310_compat) {
- ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
- if (ret) {
- pr_warn("%s: failed to get pl310-cache base %d!\n",
- __func__, ret);
- goto pl310_cache_map_failed;
- }
- }
+ pm_info->gpc_base.pbase = MX6Q_GPC_BASE_ADDR;
+ pm_info->gpc_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_GPC_BASE_ADDR);
+
+ pm_info->l2_base.pbase = MX6Q_L2_BASE_ADDR;
+ pm_info->l2_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_L2_BASE_ADDR);
+
+ pm_info->anatop_base.pbase = MX6Q_ANATOP_BASE_ADDR;
+ pm_info->anatop_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR);
pm_info->ddr_type = imx_mmdc_get_ddr_type();
pm_info->mmdc_io_num = socdata->mmdc_io_num;
- mmdc_offset_array = socdata->mmdc_io_offset;
+ mmdc_io_offset_array = socdata->mmdc_io_offset;
+ pm_info->mmdc_num = socdata->mmdc_num;
+ mmdc_offset_array = socdata->mmdc_offset;
for (i = 0; i < pm_info->mmdc_io_num; i++) {
pm_info->mmdc_io_val[i][0] =
- mmdc_offset_array[i];
+ mmdc_io_offset_array[i];
pm_info->mmdc_io_val[i][1] =
readl_relaxed(pm_info->iomuxc_base.vbase +
+ mmdc_io_offset_array[i]);
+ pm_info->mmdc_io_val[i][2] = 0;
+ }
+
+ /* i.MX6SLL has no DRAM RESET pin */
+ if (cpu_is_imx6sll()) {
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 2][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 1][2] = 0x1000;
+ } else {
+ if (pm_info->ddr_type == IMX_DDR_TYPE_LPDDR2) {
+ /* for LPDDR2, CKE0/1 and RESET pin need special setting */
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 3][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 2][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 1][2] = 0x80000;
+ }
+ }
+
+ /* initialize MMDC settings */
+ for (i = 0; i < pm_info->mmdc_num; i++) {
+ pm_info->mmdc_val[i][0] =
+ mmdc_offset_array[i];
+ pm_info->mmdc_val[i][1] =
+ readl_relaxed(pm_info->mmdc0_base.vbase +
mmdc_offset_array[i]);
}
+ if (cpu_is_imx6sll() && pm_info->ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3) {
+ pm_info->mmdc_val[0][1] = 0x8000;
+ pm_info->mmdc_val[2][1] = 0xa1390003;
+ pm_info->mmdc_val[3][1] = 0x400000;
+ pm_info->mmdc_val[4][1] = 0x800;
+ pm_info->mmdc_val[13][1] = 0x800;
+ pm_info->mmdc_val[14][1] = 0x20052;
+ pm_info->mmdc_val[20][1] = 0x201718;
+ pm_info->mmdc_val[21][1] = 0x8000;
+ pm_info->mmdc_val[28][1] = 0xa1310003;
+ }
+
+ /* need to overwrite the value for some mmdc registers */
+ if ((cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz()) &&
+ pm_info->ddr_type != IMX_DDR_TYPE_LPDDR2) {
+ pm_info->mmdc_val[20][1] = (pm_info->mmdc_val[20][1]
+ & 0xffff0000) | 0x0202;
+ pm_info->mmdc_val[23][1] = 0x8033;
+ }
+
+ if (cpu_is_imx6sx() &&
+ pm_info->ddr_type == IMX_DDR_TYPE_LPDDR2) {
+ pm_info->mmdc_val[0][1] = 0x8000;
+ pm_info->mmdc_val[2][1] = 0xa1390003;
+ pm_info->mmdc_val[3][1] = 0x380000;
+ pm_info->mmdc_val[4][1] = 0x800;
+ pm_info->mmdc_val[18][1] = 0x800;
+ pm_info->mmdc_val[20][1] = 0x20024;
+ pm_info->mmdc_val[23][1] = 0x1748;
+ pm_info->mmdc_val[32][1] = 0xa1310003;
+ }
+
+ if ((cpu_is_imx6ul() || cpu_is_imx6ull() || cpu_is_imx6ulz()) &&
+ pm_info->ddr_type == IMX_DDR_TYPE_LPDDR2) {
+ pm_info->mmdc_val[0][1] = 0x8000;
+ pm_info->mmdc_val[2][1] = 0xa1390003;
+ pm_info->mmdc_val[3][1] = 0x470000;
+ pm_info->mmdc_val[4][1] = 0x800;
+ pm_info->mmdc_val[13][1] = 0x800;
+ pm_info->mmdc_val[14][1] = 0x20012;
+ pm_info->mmdc_val[20][1] = 0x1748;
+ pm_info->mmdc_val[21][1] = 0x8000;
+ pm_info->mmdc_val[28][1] = 0xa1310003;
+ }
+
imx6_suspend_in_ocram_fn = fncpy(
suspend_ocram_base + sizeof(*pm_info),
&imx6_suspend,
MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
- goto put_device;
-
-pl310_cache_map_failed:
- iounmap(pm_info->gpc_base.vbase);
-gpc_map_failed:
- iounmap(pm_info->iomuxc_base.vbase);
-iomuxc_map_failed:
- iounmap(pm_info->src_base.vbase);
-src_map_failed:
- iounmap(pm_info->mmdc_base.vbase);
-put_device:
- put_device(&pdev->dev);
+ goto put_node;
+
put_node:
of_node_put(node);
@@ -616,28 +1266,6 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
IMX6Q_GPR1_GINT);
}
-static void imx6_pm_stby_poweroff(void)
-{
- imx6_set_lpm(STOP_POWER_OFF);
- imx6q_suspend_finish(0);
-
- mdelay(1000);
-
- pr_emerg("Unable to poweroff system\n");
-}
-
-static int imx6_pm_stby_poweroff_probe(void)
-{
- if (pm_power_off) {
- pr_warn("%s: pm_power_off already claimed %p %ps!\n",
- __func__, pm_power_off, pm_power_off);
- return -EBUSY;
- }
-
- pm_power_off = imx6_pm_stby_poweroff;
- return 0;
-}
-
void __init imx6_pm_ccm_init(const char *ccm_compat)
{
struct device_node *np;
@@ -654,14 +1282,14 @@ void __init imx6_pm_ccm_init(const char *ccm_compat)
val = readl_relaxed(ccm_base + CLPCR);
val &= ~BM_CLPCR_LPM;
writel_relaxed(val, ccm_base + CLPCR);
-
- if (of_property_read_bool(np, "fsl,pmic-stby-poweroff"))
- imx6_pm_stby_poweroff_probe();
}
void __init imx6q_pm_init(void)
{
- imx6_pm_common_init(&imx6q_pm_data);
+ 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);
}
void __init imx6dl_pm_init(void)
@@ -671,25 +1299,96 @@ void __init imx6dl_pm_init(void)
void __init imx6sl_pm_init(void)
{
+ struct device_node *np;
struct regmap *gpr;
- if (cpu_is_imx6sl()) {
- imx6_pm_common_init(&imx6sl_pm_data);
- } else {
+ if (cpu_is_imx6sll()) {
imx6_pm_common_init(&imx6sll_pm_data);
+ np = of_find_node_by_path(
+ "/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000");
+ if (np)
+ console_base = of_iomap(np, 0);
+ /* i.MX6SLL has bus auto clock gating function */
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
if (!IS_ERR(gpr))
regmap_update_bits(gpr, IOMUXC_GPR5,
- IMX6SLL_GPR5_AFCG_X_BYPASS_MASK, 0);
+ IOMUXC_GPR5_CLOCK_AFCG_X_BYPASS_MASK, 0);
+ return;
}
+
+ imx6_pm_common_init(&imx6sl_pm_data);
}
void __init imx6sx_pm_init(void)
{
- imx6_pm_common_init(&imx6sx_pm_data);
+ struct device_node *np;
+ struct resource res;
+
+ if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ imx6_pm_common_init(&imx6sx_lpddr2_pm_data);
+ else
+ imx6_pm_common_init(&imx6sx_pm_data);
+ if (imx_get_soc_revision() < IMX_CHIP_REVISION_1_2) {
+ /*
+ * As there is a 16K OCRAM(start from 0x8f8000)
+ * dedicated for low power function on i.MX6SX,
+ * but ROM did NOT do the ocram address change
+ * accordingly, so we need to add a data patch
+ * to workaround this issue, otherwise, system
+ * will fail to resume from DSM mode. TO1.2 fixes
+ * this issue.
+ */
+ romcp = syscon_regmap_lookup_by_compatible(
+ "fsl,imx6sx-romcp");
+ if (IS_ERR(romcp)) {
+ pr_err("failed to find fsl,imx6sx-romcp regmap\n");
+ return;
+ }
+ regmap_write(romcp, ROMC_ROMPATCH0D, iram_tlb_phys_addr);
+ regmap_update_bits(romcp, ROMC_ROMPATCHCNTL,
+ BM_ROMPATCHCNTL_0D, BM_ROMPATCHCNTL_0D);
+ regmap_update_bits(romcp, ROMC_ROMPATCHENL,
+ BM_ROMPATCHENL_0D, BM_ROMPATCHENL_0D);
+ regmap_write(romcp, ROMC_ROMPATCH0A,
+ ROM_ADDR_FOR_INTERNAL_RAM_BASE);
+ regmap_update_bits(romcp, ROMC_ROMPATCHCNTL,
+ BM_ROMPATCHCNTL_DIS, ~BM_ROMPATCHCNTL_DIS);
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mega-fast-sram");
+ ocram_base = of_iomap(np, 0);
+ WARN_ON(!ocram_base);
+ WARN_ON(of_address_to_resource(np, 0, &res));
+ ocram_size = resource_size(&res);
+ ocram_saved_in_ddr = kzalloc(ocram_size, GFP_KERNEL);
+ WARN_ON(!ocram_saved_in_ddr);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000");
+ if (np)
+ console_base = of_iomap(np, 0);
+ if (imx_src_is_m4_enabled()) {
+ np = of_find_compatible_node(NULL, NULL,
+ "fsl,imx6sx-qspi-m4-restore");
+ if (np)
+ qspi_base = of_iomap(np, 0);
+ WARN_ON(!qspi_base);
+ }
}
void __init imx6ul_pm_init(void)
{
- imx6_pm_common_init(&imx6ul_pm_data);
+ struct device_node *np;
+
+ if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ imx6_pm_common_init(&imx6ul_lpddr2_pm_data);
+ else
+ imx6_pm_common_init(&imx6ul_pm_data);
+
+ if (cpu_is_imx6ull() || cpu_is_imx6ulz()) {
+ np = of_find_node_by_path(
+ "/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000");
+ if (np)
+ console_base = of_iomap(np, 0);
+ }
}
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c
new file mode 100644
index 000000000000..e59cbee6dfc2
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -0,0 +1,1230 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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/busfreq-imx.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/genalloc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/mach/map.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include <uapi/linux/psci.h>
+
+#include "common.h"
+#include "hardware.h"
+#include "cpuidle.h"
+
+#define MX7_SUSPEND_OCRAM_SIZE 0x1000
+#define MX7_MAX_DDRC_NUM 32
+#define MX7_MAX_DDRC_PHY_NUM 16
+
+#define MX7_SUSPEND_IRAM_ADDR_OFFSET 0
+#define READ_DATA_FROM_HARDWARE 0
+
+#define UART_UCR1 0x80
+#define UART_UCR2 0x84
+#define UART_UCR3 0x88
+#define UART_UCR4 0x8c
+#define UART_UFCR 0x90
+#define UART_UESC 0x9c
+#define UART_UTIM 0xa0
+#define UART_UBIR 0xa4
+#define UART_UBMR 0xa8
+#define UART_UBRC 0xac
+#define UART_UTS 0xb4
+
+#define MAX_IOMUXC_GPR 23
+#define MAX_UART_IO 4
+#define MAX_CCM_LPCG 167
+#define MAX_GPT 3
+#define MAX_GPIO_ROW 7
+#define MAX_GPIO_COL 8
+
+#define UART_RX_IO 0x128
+#define UART_RX_PAD 0x398
+#define UART_TX_IO 0x12c
+#define UART_TX_PAD 0x39c
+
+#define GPT_CR 0x0
+#define GPT_PR 0x4
+#define GPT_IR 0xc
+
+#define CCM_LPCG_START 0x4040
+#define CCM_LPCG_STEP 0x10
+#define CCM_EIM_LPCG 0x4160
+#define CCM_PXP_LPCG 0x44c0
+#define CCM_PCIE_LPCG 0x4600
+
+#define BM_CCM_ROOT_POST_PODF 0x3f
+#define BM_CCM_ROOT_PRE_PODF 0x70000
+#define BM_CCM_ROOT_MUX 0x7000000
+#define BM_CCM_ROOT_ENABLE 0x10000000
+
+#define SYS_COUNTER_CNTSR 0x4
+#define BM_SYS_COUNTER_CNTSR_FCR1 0x200
+#define BM_SYS_COUNTER_CNTSR_FCR0 0x100
+#define BM_SYS_COUNTER_CNTCR_FCR1 0x200
+#define BM_SYS_COUNTER_CNTCR_FCR0 0x100
+
+#define PFD_A_OFFSET 0xc0
+#define PFD_B_OFFSET 0xd0
+
+#define PLL_ARM_OFFSET 0x60
+#define PLL_DDR_OFFSET 0x70
+#define PLL_DDR_SS_OFFSET 0x80
+#define PLL_DDR_NUM_OFFSET 0x90
+#define PLL_DDR_DENOM_OFFSET 0xa0
+#define PLL_480_OFFSET 0xb0
+#define PLL_ENET_OFFSET 0xe0
+#define PLL_AUDIO_OFFSET 0xf0
+#define PLL_AUDIO_SS_OFFSET 0x100
+#define PLL_AUDIO_NUM_OFFSET 0x110
+#define PLL_AUDIO_DENOM_OFFSET 0x120
+#define PLL_VIDEO_OFFSET 0x130
+#define PLL_VIDEO_SS_OFFSET 0x140
+#define PLL_VIDEO_NUM_OFFSET 0x150
+#define PLL_VIDEO_DENOM_OFFSET 0x160
+
+#define REG_SET 0x4
+#define REG_CLR 0x8
+
+#define GPIO_DR 0x0
+#define GPIO_GDIR 0x4
+#define GPIO_ICR1 0xc
+#define GPIO_ICR2 0x10
+#define GPIO_IMR 0x14
+#define GPIO_EDGE 0x1c
+
+#define M4RCR 0x0C
+#define M4_SP_OFF 0x00
+#define M4_PC_OFF 0x04
+#define M4_RCR_HALT 0xAB
+#define M4_RCR_GO 0xAA
+#define M4_OCRAMS_RESERVED_SIZE 0xc
+
+extern unsigned long iram_tlb_base_addr;
+extern unsigned long iram_tlb_phys_addr;
+
+static unsigned int *ocram_saved_in_ddr;
+static void __iomem *ocram_base;
+static unsigned int ocram_size;
+static unsigned int *lpm_ocram_saved_in_ddr;
+static void __iomem *lpm_ocram_base;
+
+static unsigned int *lpm_m4tcm_saved_in_ddr;
+static void __iomem *lpm_m4tcm_base;
+static void __iomem *m4_bootrom_base;
+
+static unsigned int lpm_ocram_size;
+static void __iomem *ccm_base;
+static void __iomem *lpsr_base;
+static void __iomem *console_base;
+static void __iomem *suspend_ocram_base;
+static void __iomem *iomuxc_base;
+static void __iomem *gpt1_base;
+static void __iomem *system_counter_ctrl_base;
+static void __iomem *system_counter_cmp_base;
+static void __iomem *gpio1_base;
+static void (*imx7_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
+struct imx7_cpu_pm_info *pm_info;
+static bool lpsr_enabled;
+static u32 iomuxc_gpr[MAX_IOMUXC_GPR];
+static u32 uart1_io[MAX_UART_IO];
+static u32 ccm_lpcg[MAX_CCM_LPCG];
+static u32 ccm_root[][2] = {
+ {0x8000, 0}, {0x8080, 0}, {0x8100, 0}, {0x8800, 0},
+ {0x8880, 0}, {0x8900, 0}, {0x8980, 0}, {0x9000, 0},
+ {0x9800, 0}, {0x9880, 0}, {0xa000, 0}, {0xa080, 0},
+ {0xa100, 0}, {0xa180, 0}, {0xa200, 0}, {0xa280, 0},
+ {0xa300, 0}, {0xa380, 0}, {0xa400, 0}, {0xa480, 0},
+ {0xa500, 0}, {0xa580, 0}, {0xa600, 0}, {0xa680, 0},
+ {0xa700, 0}, {0xa780, 0}, {0xa800, 0}, {0xa880, 0},
+ {0xa900, 0}, {0xa980, 0}, {0xaa00, 0}, {0xaa80, 0},
+ {0xab00, 0}, {0xab80, 0}, {0xac00, 0}, {0xac80, 0},
+ {0xad00, 0}, {0xad80, 0}, {0xae00, 0}, {0xae80, 0},
+ {0xaf00, 0}, {0xaf80, 0}, {0xb000, 0}, {0xb080, 0},
+ {0xb100, 0}, {0xb180, 0}, {0xb200, 0}, {0xb280, 0},
+ {0xb300, 0}, {0xb380, 0}, {0xb400, 0}, {0xb480, 0},
+ {0xb500, 0}, {0xb580, 0}, {0xb600, 0}, {0xb680, 0},
+ {0xb700, 0}, {0xb780, 0}, {0xb800, 0}, {0xb880, 0},
+ {0xb900, 0}, {0xb980, 0}, {0xba00, 0}, {0xba80, 0},
+ {0xbb00, 0}, {0xbb80, 0}, {0xbc00, 0}, {0xbc80, 0},
+ {0xbd00, 0}, {0xbd80, 0}, {0xbe00, 0},
+};
+static u32 pfd_a, pfd_b;
+static u32 pll[15];
+static u32 gpt1_regs[MAX_GPT];
+static u32 sys_ctrl_reg, sys_cmp_reg;
+static u32 gpio_reg[MAX_GPIO_ROW][MAX_GPIO_COL];
+/*
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ * .
+ * .
+ * .
+ * ^
+ * ^
+ * ^
+ * imx7_suspend code
+ * PM_INFO structure(imx7_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+struct imx7_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+struct imx7_pm_socdata {
+ u32 ddr_type;
+ const char *ddrc_compat;
+ const char *src_compat;
+ const char *iomuxc_compat;
+ const char *gpc_compat;
+ const u32 ddrc_num;
+ const u32 (*ddrc_offset)[2];
+ const u32 ddrc_phy_num;
+ const u32 (*ddrc_phy_offset)[2];
+};
+
+static const u32 imx7d_ddrc_lpddr3_setting[][2] __initconst = {
+ { 0x0, READ_DATA_FROM_HARDWARE },
+ { 0x1a0, READ_DATA_FROM_HARDWARE },
+ { 0x1a4, READ_DATA_FROM_HARDWARE },
+ { 0x1a8, READ_DATA_FROM_HARDWARE },
+ { 0x64, READ_DATA_FROM_HARDWARE },
+ { 0xd0, READ_DATA_FROM_HARDWARE },
+ { 0xdc, READ_DATA_FROM_HARDWARE },
+ { 0xe0, READ_DATA_FROM_HARDWARE },
+ { 0xe4, READ_DATA_FROM_HARDWARE },
+ { 0xf4, READ_DATA_FROM_HARDWARE },
+ { 0x100, READ_DATA_FROM_HARDWARE },
+ { 0x104, READ_DATA_FROM_HARDWARE },
+ { 0x108, READ_DATA_FROM_HARDWARE },
+ { 0x10c, READ_DATA_FROM_HARDWARE },
+ { 0x110, READ_DATA_FROM_HARDWARE },
+ { 0x114, READ_DATA_FROM_HARDWARE },
+ { 0x118, READ_DATA_FROM_HARDWARE },
+ { 0x120, READ_DATA_FROM_HARDWARE },
+ { 0x11c, READ_DATA_FROM_HARDWARE },
+ { 0x180, READ_DATA_FROM_HARDWARE },
+ { 0x184, READ_DATA_FROM_HARDWARE },
+ { 0x190, READ_DATA_FROM_HARDWARE },
+ { 0x194, READ_DATA_FROM_HARDWARE },
+ { 0x200, READ_DATA_FROM_HARDWARE },
+ { 0x204, READ_DATA_FROM_HARDWARE },
+ { 0x210, READ_DATA_FROM_HARDWARE },
+ { 0x214, READ_DATA_FROM_HARDWARE },
+ { 0x218, READ_DATA_FROM_HARDWARE },
+ { 0x240, READ_DATA_FROM_HARDWARE },
+ { 0x244, READ_DATA_FROM_HARDWARE },
+};
+
+static const u32 imx7d_ddrc_phy_lpddr3_setting[][2] __initconst = {
+ { 0x0, READ_DATA_FROM_HARDWARE },
+ { 0x4, READ_DATA_FROM_HARDWARE },
+ { 0x8, READ_DATA_FROM_HARDWARE },
+ { 0x10, READ_DATA_FROM_HARDWARE },
+ { 0xb0, READ_DATA_FROM_HARDWARE },
+ { 0x1c, READ_DATA_FROM_HARDWARE },
+ { 0x9c, READ_DATA_FROM_HARDWARE },
+ { 0x7c, READ_DATA_FROM_HARDWARE },
+ { 0x80, READ_DATA_FROM_HARDWARE },
+ { 0x84, READ_DATA_FROM_HARDWARE },
+ { 0x88, READ_DATA_FROM_HARDWARE },
+ { 0x6c, READ_DATA_FROM_HARDWARE },
+ { 0x20, READ_DATA_FROM_HARDWARE },
+ { 0x30, READ_DATA_FROM_HARDWARE },
+ { 0x50, 0x01000008 },
+ { 0x50, 0x00000008 },
+ { 0xc0, 0x0e487304 },
+ { 0xc0, 0x0e4c7304 },
+ { 0xc0, 0x0e4c7306 },
+ { 0xc0, 0x0e487304 },
+};
+
+static const u32 imx7d_ddrc_ddr3_setting[][2] __initconst = {
+ { 0x0, READ_DATA_FROM_HARDWARE },
+ { 0x1a0, READ_DATA_FROM_HARDWARE },
+ { 0x1a4, READ_DATA_FROM_HARDWARE },
+ { 0x1a8, READ_DATA_FROM_HARDWARE },
+ { 0x64, READ_DATA_FROM_HARDWARE },
+ { 0x490, READ_DATA_FROM_HARDWARE },
+ { 0xd0, READ_DATA_FROM_HARDWARE },
+ { 0xd4, READ_DATA_FROM_HARDWARE },
+ { 0xdc, READ_DATA_FROM_HARDWARE },
+ { 0xe0, READ_DATA_FROM_HARDWARE },
+ { 0xe4, READ_DATA_FROM_HARDWARE },
+ { 0xf4, READ_DATA_FROM_HARDWARE },
+ { 0x100, READ_DATA_FROM_HARDWARE },
+ { 0x104, READ_DATA_FROM_HARDWARE },
+ { 0x108, READ_DATA_FROM_HARDWARE },
+ { 0x10c, READ_DATA_FROM_HARDWARE },
+ { 0x110, READ_DATA_FROM_HARDWARE },
+ { 0x114, READ_DATA_FROM_HARDWARE },
+ { 0x120, READ_DATA_FROM_HARDWARE },
+ { 0x180, READ_DATA_FROM_HARDWARE },
+ { 0x190, READ_DATA_FROM_HARDWARE },
+ { 0x194, READ_DATA_FROM_HARDWARE },
+ { 0x200, READ_DATA_FROM_HARDWARE },
+ { 0x204, READ_DATA_FROM_HARDWARE },
+ { 0x210, READ_DATA_FROM_HARDWARE },
+ { 0x214, READ_DATA_FROM_HARDWARE },
+ { 0x218, READ_DATA_FROM_HARDWARE },
+ { 0x240, READ_DATA_FROM_HARDWARE },
+ { 0x244, READ_DATA_FROM_HARDWARE },
+};
+
+static const u32 imx7d_ddrc_phy_ddr3_setting[][2] __initconst = {
+ { 0x0, READ_DATA_FROM_HARDWARE },
+ { 0x4, READ_DATA_FROM_HARDWARE },
+ { 0x10, READ_DATA_FROM_HARDWARE },
+ { 0xb0, READ_DATA_FROM_HARDWARE },
+ { 0x9c, READ_DATA_FROM_HARDWARE },
+ { 0x7c, READ_DATA_FROM_HARDWARE },
+ { 0x80, READ_DATA_FROM_HARDWARE },
+ { 0x84, READ_DATA_FROM_HARDWARE },
+ { 0x88, READ_DATA_FROM_HARDWARE },
+ { 0x6c, READ_DATA_FROM_HARDWARE },
+ { 0x20, READ_DATA_FROM_HARDWARE },
+ { 0x30, READ_DATA_FROM_HARDWARE },
+ { 0x50, 0x01000010 },
+ { 0x50, 0x00000010 },
+ { 0xc0, 0x0e407304 },
+ { 0xc0, 0x0e447304 },
+ { 0xc0, 0x0e447306 },
+ { 0xc0, 0x0e407304 },
+};
+
+static const struct imx7_pm_socdata imx7d_pm_data_lpddr3 __initconst = {
+ .ddrc_compat = "fsl,imx7d-ddrc",
+ .src_compat = "fsl,imx7d-src",
+ .iomuxc_compat = "fsl,imx7d-iomuxc",
+ .gpc_compat = "fsl,imx7d-gpc",
+ .ddrc_num = ARRAY_SIZE(imx7d_ddrc_lpddr3_setting),
+ .ddrc_offset = imx7d_ddrc_lpddr3_setting,
+ .ddrc_phy_num = ARRAY_SIZE(imx7d_ddrc_phy_lpddr3_setting),
+ .ddrc_phy_offset = imx7d_ddrc_phy_lpddr3_setting,
+};
+
+static const struct imx7_pm_socdata imx7d_pm_data_ddr3 __initconst = {
+ .ddrc_compat = "fsl,imx7d-ddrc",
+ .src_compat = "fsl,imx7d-src",
+ .iomuxc_compat = "fsl,imx7d-iomuxc",
+ .gpc_compat = "fsl,imx7d-gpc",
+ .ddrc_num = ARRAY_SIZE(imx7d_ddrc_ddr3_setting),
+ .ddrc_offset = imx7d_ddrc_ddr3_setting,
+ .ddrc_phy_num = ARRAY_SIZE(imx7d_ddrc_phy_ddr3_setting),
+ .ddrc_phy_offset = imx7d_ddrc_phy_ddr3_setting,
+};
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * suspend code(arch/arm/mach-imx/suspend-imx7.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/suspend-imx7.S must be also changed accordingly,
+ * otherwise, the suspend to ocram function will be broken!
+ */
+struct imx7_cpu_pm_info {
+ u32 m4_reserve0;
+ u32 m4_reserve1;
+ u32 m4_reserve2;
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 ddr_type;
+ u32 pm_info_size; /* Size of pm_info. */
+ struct imx7_pm_base ddrc_base;
+ struct imx7_pm_base ddrc_phy_base;
+ struct imx7_pm_base src_base;
+ struct imx7_pm_base iomuxc_gpr_base;
+ struct imx7_pm_base ccm_base;
+ struct imx7_pm_base gpc_base;
+ struct imx7_pm_base snvs_base;
+ struct imx7_pm_base anatop_base;
+ struct imx7_pm_base lpsr_base;
+ struct imx7_pm_base gic_base;
+ u32 ttbr1; /* Store TTBR1 */
+ u32 ddrc_num; /* Number of DDRC which need saved/restored. */
+ u32 ddrc_val[MX7_MAX_DDRC_NUM][2]; /* To save offset and value */
+ u32 ddrc_phy_num; /* Number of DDRC which need saved/restored. */
+ u32 ddrc_phy_val[MX7_MAX_DDRC_NUM][2]; /* To save offset and value */
+} __aligned(8);
+
+static struct map_desc imx7_pm_io_desc[] __initdata = {
+ imx_map_entry(MX7D, AIPS1, MT_DEVICE),
+ imx_map_entry(MX7D, AIPS2, MT_DEVICE),
+ imx_map_entry(MX7D, AIPS3, MT_DEVICE),
+};
+
+static const char * const low_power_ocram_match[] __initconst = {
+ "fsl,lpm-sram",
+ NULL
+};
+
+static void imx7_gpio_save(void)
+{
+ u32 i;
+
+ for (i = 0; i < 7; i++) {
+ gpio_reg[i][0] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_DR);
+ gpio_reg[i][1] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_GDIR);
+ gpio_reg[i][3] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_ICR1);
+ gpio_reg[i][4] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_ICR2);
+ gpio_reg[i][5] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_IMR);
+ gpio_reg[i][7] = readl_relaxed(gpio1_base +
+ (i << 16) + GPIO_EDGE);
+ }
+}
+
+static void imx7_gpio_restore(void)
+{
+ u32 i, val;
+
+ for (i = 0; i < 7; i++) {
+ writel_relaxed(gpio_reg[i][1], gpio1_base +
+ (i << 16) + GPIO_GDIR);
+ writel_relaxed(gpio_reg[i][3], gpio1_base +
+ (i << 16) + GPIO_ICR1);
+ writel_relaxed(gpio_reg[i][4], gpio1_base +
+ (i << 16) + GPIO_ICR2);
+ writel_relaxed(gpio_reg[i][5], gpio1_base +
+ (i << 16) + GPIO_IMR);
+ writel_relaxed(gpio_reg[i][7], gpio1_base +
+ (i << 16) + GPIO_EDGE);
+ /* only restore output gpio value */
+ val = readl_relaxed(gpio1_base + (i << 16) + GPIO_DR) |
+ (gpio_reg[i][0] & gpio_reg[i][1]);
+ writel_relaxed(val, gpio1_base + (i << 16) + GPIO_DR);
+ }
+}
+
+static void imx7_ccm_save(void)
+{
+ u32 i;
+
+ for (i = 0; i < MAX_CCM_LPCG; i++)
+ ccm_lpcg[i] = readl_relaxed(pm_info->ccm_base.vbase +
+ i * CCM_LPCG_STEP + CCM_LPCG_START);
+ pfd_a = readl_relaxed(pm_info->anatop_base.vbase + PFD_A_OFFSET);
+ pfd_b = readl_relaxed(pm_info->anatop_base.vbase + PFD_B_OFFSET);
+
+ pll[0] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_ARM_OFFSET);
+ pll[1] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_DDR_OFFSET);
+ pll[2] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_DDR_SS_OFFSET);
+ pll[3] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_DDR_NUM_OFFSET);
+ pll[4] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_DDR_DENOM_OFFSET);
+ pll[5] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_480_OFFSET);
+ pll[6] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_ENET_OFFSET);
+ pll[7] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_AUDIO_OFFSET);
+ pll[8] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_AUDIO_SS_OFFSET);
+ pll[9] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_AUDIO_NUM_OFFSET);
+ pll[10] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_AUDIO_DENOM_OFFSET);
+ pll[11] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_VIDEO_OFFSET);
+ pll[12] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_VIDEO_SS_OFFSET);
+ pll[13] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_VIDEO_NUM_OFFSET);
+ pll[14] = readl_relaxed(pm_info->anatop_base.vbase +
+ PLL_VIDEO_DENOM_OFFSET);
+
+ /* enable all PLLs/PFDs for saving CCM root */
+ writel_relaxed(0x1c000070, pm_info->anatop_base.vbase +
+ PLL_480_OFFSET + 0x8);
+ writel_relaxed(0x80808080, pm_info->anatop_base.vbase +
+ PFD_A_OFFSET + 0x8);
+ writel_relaxed(0x80808080, pm_info->anatop_base.vbase +
+ PFD_B_OFFSET + 0x8);
+ writel_relaxed(0x1fc0, pm_info->anatop_base.vbase +
+ PLL_ENET_OFFSET + 0x4);
+ writel_relaxed(0x12000, pm_info->anatop_base.vbase +
+ PLL_AUDIO_OFFSET);
+ writel_relaxed(0x12000, pm_info->anatop_base.vbase +
+ PLL_VIDEO_OFFSET);
+
+ for (i = 0; i < sizeof(ccm_root) / 8; i++)
+ ccm_root[i][1] = readl_relaxed(
+ pm_info->ccm_base.vbase + ccm_root[i][0]);
+}
+
+static void imx7_ccm_restore(void)
+{
+ u32 i, val;
+
+ /* enable all PLLs/PFDs for restoring CCM root */
+ writel_relaxed(0x1c000070, pm_info->anatop_base.vbase +
+ PLL_480_OFFSET + REG_CLR);
+ writel_relaxed(0x80808080, pm_info->anatop_base.vbase +
+ PFD_A_OFFSET + REG_CLR);
+ writel_relaxed(0x80808080, pm_info->anatop_base.vbase +
+ PFD_B_OFFSET + REG_CLR);
+ writel_relaxed(0x1fc0, pm_info->anatop_base.vbase +
+ PLL_ENET_OFFSET + REG_SET);
+ writel_relaxed(0x12000, pm_info->anatop_base.vbase +
+ PLL_AUDIO_OFFSET);
+ writel_relaxed(0x12000, pm_info->anatop_base.vbase +
+ PLL_VIDEO_OFFSET);
+
+ for (i = 0; i < sizeof(ccm_root) / 8; i++) {
+ val = readl_relaxed(pm_info->ccm_base.vbase + ccm_root[i][0]);
+ /* restore post podf */
+ val &= ~BM_CCM_ROOT_POST_PODF;
+ val |= ccm_root[i][1] & BM_CCM_ROOT_POST_PODF;
+ writel_relaxed(val, pm_info->ccm_base.vbase + ccm_root[i][0]);
+ /* resotre pre podf */
+ val &= ~BM_CCM_ROOT_PRE_PODF;
+ val |= ccm_root[i][1] & BM_CCM_ROOT_PRE_PODF;
+ writel_relaxed(val, pm_info->ccm_base.vbase + ccm_root[i][0]);
+ /* restore mux */
+ val &= ~BM_CCM_ROOT_MUX;
+ val |= ccm_root[i][1] & BM_CCM_ROOT_MUX;
+ writel_relaxed(val, pm_info->ccm_base.vbase + ccm_root[i][0]);
+ /* restore enable */
+ val &= ~BM_CCM_ROOT_ENABLE;
+ val |= ccm_root[i][1] & BM_CCM_ROOT_ENABLE;
+ writel_relaxed(val, pm_info->ccm_base.vbase + ccm_root[i][0]);
+ }
+
+ /* restore PLLs */
+ writel_relaxed(pll[0], pm_info->anatop_base.vbase +
+ PLL_ARM_OFFSET);
+ writel_relaxed(pll[1], pm_info->anatop_base.vbase +
+ PLL_DDR_OFFSET);
+ writel_relaxed(pll[2], pm_info->anatop_base.vbase +
+ PLL_DDR_SS_OFFSET);
+ writel_relaxed(pll[3], pm_info->anatop_base.vbase +
+ PLL_DDR_NUM_OFFSET);
+ writel_relaxed(pll[4], pm_info->anatop_base.vbase +
+ PLL_DDR_DENOM_OFFSET);
+ writel_relaxed(pll[5], pm_info->anatop_base.vbase +
+ PLL_480_OFFSET);
+ writel_relaxed(pll[6], pm_info->anatop_base.vbase +
+ PLL_ENET_OFFSET);
+ writel_relaxed(pll[7], pm_info->anatop_base.vbase +
+ PLL_AUDIO_OFFSET);
+ writel_relaxed(pll[8], pm_info->anatop_base.vbase +
+ PLL_AUDIO_SS_OFFSET);
+ writel_relaxed(pll[9], pm_info->anatop_base.vbase +
+ PLL_AUDIO_NUM_OFFSET);
+ writel_relaxed(pll[10], pm_info->anatop_base.vbase +
+ PLL_AUDIO_DENOM_OFFSET);
+ writel_relaxed(pll[11], pm_info->anatop_base.vbase +
+ PLL_VIDEO_OFFSET);
+ writel_relaxed(pll[12], pm_info->anatop_base.vbase +
+ PLL_VIDEO_SS_OFFSET);
+ writel_relaxed(pll[13], pm_info->anatop_base.vbase +
+ PLL_VIDEO_NUM_OFFSET);
+ writel_relaxed(pll[14], pm_info->anatop_base.vbase +
+ PLL_VIDEO_DENOM_OFFSET);
+
+ for (i = 0; i < MAX_CCM_LPCG; i++)
+ writel_relaxed(ccm_lpcg[i], pm_info->ccm_base.vbase +
+ i * CCM_LPCG_STEP + CCM_LPCG_START);
+ /* restore PFDs */
+ writel_relaxed(pfd_a & 0x80808080,
+ pm_info->anatop_base.vbase + PFD_A_OFFSET + REG_SET);
+ writel_relaxed(pfd_a, pm_info->anatop_base.vbase + PFD_A_OFFSET);
+
+ writel_relaxed(pfd_b & 0x80808080,
+ pm_info->anatop_base.vbase + PFD_B_OFFSET + REG_SET);
+ writel_relaxed(pfd_b, pm_info->anatop_base.vbase + PFD_B_OFFSET);
+}
+
+static void imx7_sys_counter_save(void)
+{
+ sys_ctrl_reg = readl_relaxed(system_counter_ctrl_base);
+ sys_cmp_reg = readl_relaxed(system_counter_cmp_base);
+}
+
+static void imx7_sys_counter_restore(void)
+{
+ writel_relaxed(sys_ctrl_reg, system_counter_ctrl_base);
+ writel_relaxed(sys_cmp_reg, system_counter_cmp_base);
+}
+
+static void imx7_gpt_save(void)
+{
+ gpt1_regs[0] = readl_relaxed(gpt1_base + GPT_CR);
+ gpt1_regs[1] = readl_relaxed(gpt1_base + GPT_PR);
+ gpt1_regs[2] = readl_relaxed(gpt1_base + GPT_IR);
+}
+
+static void imx7_gpt_restore(void)
+{
+ writel_relaxed(gpt1_regs[0], gpt1_base + GPT_CR);
+ writel_relaxed(gpt1_regs[1], gpt1_base + GPT_PR);
+ writel_relaxed(gpt1_regs[2], gpt1_base + GPT_IR);
+}
+
+static void imx7_iomuxc_gpr_save(void)
+{
+ u32 i;
+
+ for (i = 0; i < MAX_IOMUXC_GPR; i++)
+ iomuxc_gpr[i] = readl_relaxed(
+ pm_info->iomuxc_gpr_base.vbase + i * 4);
+}
+
+static void imx7_iomuxc_gpr_restore(void)
+{
+ u32 i;
+
+ for (i = 0; i < MAX_IOMUXC_GPR; i++)
+ writel_relaxed(iomuxc_gpr[i],
+ pm_info->iomuxc_gpr_base.vbase + i * 4);
+}
+
+static void imx7_console_save(unsigned int *regs)
+{
+ if (!console_base)
+ return;
+
+ regs[0] = readl_relaxed(console_base + UART_UCR1);
+ regs[1] = readl_relaxed(console_base + UART_UCR2);
+ regs[2] = readl_relaxed(console_base + UART_UCR3);
+ regs[3] = readl_relaxed(console_base + UART_UCR4);
+ regs[4] = readl_relaxed(console_base + UART_UFCR);
+ regs[5] = readl_relaxed(console_base + UART_UESC);
+ regs[6] = readl_relaxed(console_base + UART_UTIM);
+ regs[7] = readl_relaxed(console_base + UART_UBIR);
+ regs[8] = readl_relaxed(console_base + UART_UBMR);
+ regs[9] = readl_relaxed(console_base + UART_UTS);
+}
+
+static void imx7_console_io_save(void)
+{
+ /* save uart1 io, driver resume is too late */
+ uart1_io[0] = readl_relaxed(iomuxc_base + UART_RX_IO);
+ uart1_io[1] = readl_relaxed(iomuxc_base + UART_RX_PAD);
+ uart1_io[2] = readl_relaxed(iomuxc_base + UART_TX_IO);
+ uart1_io[3] = readl_relaxed(iomuxc_base + UART_TX_PAD);
+}
+
+static void imx7_console_restore(unsigned int *regs)
+{
+ if (!console_base)
+ return;
+
+ writel_relaxed(regs[4], console_base + UART_UFCR);
+ writel_relaxed(regs[5], console_base + UART_UESC);
+ writel_relaxed(regs[6], console_base + UART_UTIM);
+ writel_relaxed(regs[7], console_base + UART_UBIR);
+ writel_relaxed(regs[8], console_base + UART_UBMR);
+ writel_relaxed(regs[9], console_base + UART_UTS);
+ writel_relaxed(regs[0], console_base + UART_UCR1);
+ writel_relaxed(regs[1] | 0x1, console_base + UART_UCR2);
+ writel_relaxed(regs[2], console_base + UART_UCR3);
+ writel_relaxed(regs[3], console_base + UART_UCR4);
+}
+
+static void imx7_console_io_restore(void)
+{
+ /* restore uart1 io */
+ writel_relaxed(uart1_io[0], iomuxc_base + UART_RX_IO);
+ writel_relaxed(uart1_io[1], iomuxc_base + UART_RX_PAD);
+ writel_relaxed(uart1_io[2], iomuxc_base + UART_TX_IO);
+ writel_relaxed(uart1_io[3], iomuxc_base + UART_TX_PAD);
+}
+
+#define MX7D_SUSPEND_POWERDWN_PARAM \
+ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+#define MX7D_SUSPEND_STANDBY_PARAM \
+ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_STANDBY << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+static int imx7_suspend_finish(unsigned long val)
+{
+ u32 state;
+
+ if (val == 0)
+ state = MX7D_SUSPEND_POWERDWN_PARAM;
+ else
+ state = MX7D_SUSPEND_STANDBY_PARAM;
+
+ if (psci_ops.cpu_suspend) {
+ return psci_ops.cpu_suspend(state, __pa(cpu_resume));
+ }
+
+ if (!imx7_suspend_in_ocram_fn) {
+ cpu_do_idle();
+ } else {
+ /*
+ * call low level suspend function in ocram,
+ * as we need to float DDR IO.
+ */
+ local_flush_tlb_all();
+ imx7_suspend_in_ocram_fn(suspend_ocram_base);
+ }
+
+ return 0;
+}
+
+static void imx7_pm_set_lpsr_resume_addr(unsigned long addr)
+{
+ writel_relaxed(addr, pm_info->lpsr_base.vbase);
+}
+
+static int imx7_pm_is_resume_from_lpsr(void)
+{
+ return readl_relaxed(lpsr_base);
+}
+
+static int imx7_pm_enter(suspend_state_t state)
+{
+ unsigned int console_saved_reg[10] = {0};
+ u32 val;
+
+ if (!iram_tlb_base_addr) {
+ pr_warn("No IRAM/OCRAM memory allocated for suspend/resume \
+ code. Please ensure device tree has an entry for \
+ fsl,lpm-sram.\n");
+ return -EINVAL;
+ }
+
+ /*
+ * arm_arch_timer driver requires system counter to be
+ * a clock source with CLOCK_SOURCE_SUSPEND_NONSTOP flag
+ * set, which means hardware system counter needs to keep
+ * running during suspend, as the base clock for system
+ * counter is 24MHz which will be disabled in STOP mode,
+ * so we need to switch system counter's clock to alternate
+ * (lower) clock, it is based on 32K, from block guide, there
+ * is no special flow needs to be followed, system counter
+ * hardware will handle the clock transition.
+ */
+ val = readl_relaxed(system_counter_ctrl_base);
+ val &= ~BM_SYS_COUNTER_CNTCR_FCR0;
+ val |= BM_SYS_COUNTER_CNTCR_FCR1;
+ writel_relaxed(val, system_counter_ctrl_base);
+ while (!(readl_relaxed(system_counter_ctrl_base + SYS_COUNTER_CNTSR)
+ & BM_SYS_COUNTER_CNTSR_FCR1))
+ ;
+
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ imx_anatop_pre_suspend();
+ imx_gpcv2_pre_suspend(false);
+
+ /* Zzz ... */
+ if (psci_ops.cpu_suspend)
+ cpu_suspend(1, imx7_suspend_finish);
+ else
+ imx7_suspend_in_ocram_fn(suspend_ocram_base);
+
+ imx_anatop_post_resume();
+ imx_gpcv2_post_resume();
+ break;
+ case PM_SUSPEND_MEM:
+ imx_anatop_pre_suspend();
+ imx_gpcv2_pre_suspend(true);
+ if (imx_gpcv2_is_mf_mix_off()) {
+ /*
+ * per design requirement, EXSC for PCIe/EIM/PXP
+ * will need clock to recover RDC setting on
+ * resume, so enable PCIe/EIM LPCG for RDC
+ * recovery when M/F mix off
+ */
+ writel_relaxed(0x3, pm_info->ccm_base.vbase +
+ CCM_EIM_LPCG);
+ writel_relaxed(0x3, pm_info->ccm_base.vbase +
+ CCM_PXP_LPCG);
+ writel_relaxed(0x3, pm_info->ccm_base.vbase +
+ CCM_PCIE_LPCG);
+ /* stop m4 if mix will also be shutdown */
+ if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) {
+ writel(M4_RCR_HALT,
+ pm_info->src_base.vbase + M4RCR);
+ imx_gpcv2_enable_wakeup_for_m4();
+ }
+ imx7_console_save(console_saved_reg);
+ memcpy(ocram_saved_in_ddr, ocram_base, ocram_size);
+ if (lpsr_enabled) {
+ imx7_pm_set_lpsr_resume_addr(pm_info->resume_addr);
+ imx7_console_io_save();
+ memcpy(lpm_ocram_saved_in_ddr, lpm_ocram_base,
+ lpm_ocram_size);
+ imx7_iomuxc_gpr_save();
+ imx7_ccm_save();
+ imx7_gpt_save();
+ imx7_sys_counter_save();
+ imx7_gpio_save();
+ }
+ }
+
+ /* Zzz ... */
+ cpu_suspend(0, imx7_suspend_finish);
+
+ if (imx7_pm_is_resume_from_lpsr()) {
+ imx7_console_io_restore();
+ memcpy(lpm_ocram_base, lpm_ocram_saved_in_ddr,
+ lpm_ocram_size);
+ imx7_iomuxc_gpr_restore();
+ imx7_ccm_restore();
+ imx7_gpt_restore();
+ imx7_sys_counter_restore();
+ imx7_gpio_restore();
+ imx7d_enable_rcosc();
+ }
+ if (imx_gpcv2_is_mf_mix_off() ||
+ imx7_pm_is_resume_from_lpsr()) {
+ writel_relaxed(0x0, pm_info->ccm_base.vbase +
+ CCM_EIM_LPCG);
+ writel_relaxed(0x0, pm_info->ccm_base.vbase +
+ CCM_PXP_LPCG);
+ writel_relaxed(0x0, pm_info->ccm_base.vbase +
+ CCM_PCIE_LPCG);
+ memcpy(ocram_base, ocram_saved_in_ddr, ocram_size);
+ imx7_console_restore(console_saved_reg);
+ if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) {
+ imx_gpcv2_disable_wakeup_for_m4();
+ /* restore M4 image */
+ memcpy(lpm_m4tcm_base,
+ lpm_m4tcm_saved_in_ddr, SZ_32K);
+ /* kick m4 to enable */
+ writel(M4_RCR_GO,
+ pm_info->src_base.vbase + M4RCR);
+ /* offset high bus count for m4 image */
+ request_bus_freq(BUS_FREQ_HIGH);
+ /* restore M4 to run mode */
+ imx_mu_set_m4_run_mode();
+ /* gpc wakeup */
+ }
+ }
+ /* clear LPSR resume address */
+ imx7_pm_set_lpsr_resume_addr(0);
+ imx_anatop_post_resume();
+ imx_gpcv2_post_resume();
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* restore system counter's clock to base clock */
+ val = readl_relaxed(system_counter_ctrl_base);
+ val &= ~BM_SYS_COUNTER_CNTCR_FCR1;
+ val |= BM_SYS_COUNTER_CNTCR_FCR0;
+ writel_relaxed(val, system_counter_ctrl_base);
+ while (!(readl_relaxed(system_counter_ctrl_base + SYS_COUNTER_CNTSR)
+ & BM_SYS_COUNTER_CNTSR_FCR0))
+ ;
+
+ return 0;
+}
+
+static int imx7_pm_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
+}
+
+static const struct platform_suspend_ops imx7_pm_ops = {
+ .enter = imx7_pm_enter,
+ .valid = imx7_pm_valid,
+};
+
+void __init imx7_pm_set_ccm_base(void __iomem *base)
+{
+ ccm_base = base;
+}
+
+static struct map_desc iram_tlb_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_1M,
+ .type = MT_MEMORY_RWX_NONCACHED,
+};
+
+static int __init imx7_dt_find_lpsram(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ unsigned long lpram_addr;
+ const __be32 *prop = of_get_flat_dt_prop(node, "reg", NULL);
+
+ if (of_flat_dt_match(node, low_power_ocram_match)) {
+ if (!prop)
+ return -EINVAL;
+
+ lpram_addr = be32_to_cpup(prop);
+
+ /* We need to create a 1M page table entry. */
+ iram_tlb_io_desc.virtual = IMX_IO_P2V(lpram_addr & 0xFFF00000);
+ iram_tlb_io_desc.pfn = __phys_to_pfn(lpram_addr & 0xFFF00000);
+ iram_tlb_phys_addr = lpram_addr;
+ iram_tlb_base_addr = IMX_IO_P2V(lpram_addr);
+ iotable_init(&iram_tlb_io_desc, 1);
+ }
+
+ return 0;
+}
+
+void __init imx7_pm_map_io(void)
+{
+ unsigned long i, j;
+
+ iotable_init(imx7_pm_io_desc, ARRAY_SIZE(imx7_pm_io_desc));
+ /*
+ * Get the address of IRAM or OCRAM to be used by the low
+ * power code from the device tree.
+ */
+ WARN_ON(of_scan_flat_dt(imx7_dt_find_lpsram, NULL));
+
+ /* Return if no IRAM space is allocated for suspend/resume code. */
+ if (!iram_tlb_base_addr) {
+ pr_warn("No valid ocram available for suspend/resume!\n");
+ return;
+ }
+
+ /* TODO: Handle M4 in TEE? */
+ /* Set all entries to 0 except first 3 words reserved for M4. */
+ memset((void *)(iram_tlb_base_addr + M4_OCRAMS_RESERVED_SIZE),
+ 0, MX7_IRAM_TLB_SIZE - M4_OCRAMS_RESERVED_SIZE);
+
+ /*
+ * Make sure the IRAM virtual address has a mapping in the IRAM
+ * page table.
+ *
+ * Only use the top 12 bits [31-20] when storing the physical
+ * address in the page table as only these bits are required
+ * for 1M mapping.
+ */
+ j = ((iram_tlb_base_addr >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ (iram_tlb_phys_addr & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
+
+ /*
+ * Make sure the AIPS1 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ for (i = 0; i < 4; i++) {
+ j = ((IMX_IO_P2V(MX7D_AIPS1_BASE_ADDR + i * 0x100000) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7D_AIPS1_BASE_ADDR + i * 0x100000) & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ }
+
+ /*
+ * Make sure the AIPS2 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ for (i = 0; i < 4; i++) {
+ j = ((IMX_IO_P2V(MX7D_AIPS2_BASE_ADDR + i * 0x100000) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7D_AIPS2_BASE_ADDR + i * 0x100000) & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ }
+
+ /*
+ * Make sure the AIPS3 virtual address has a mapping
+ * in the IRAM page table.
+ */
+ for (i = 0; i < 4; i++) {
+ j = ((IMX_IO_P2V(MX7D_AIPS3_BASE_ADDR + i * 0x100000) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7D_AIPS3_BASE_ADDR + i * 0x100000) & 0xFFF00000) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ }
+
+ /*
+ * Make sure the GIC virtual address has a mapping in the
+ * IRAM page table.
+ */
+ j = ((IMX_IO_P2V(MX7D_GIC_BASE_ADDR) >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ (MX7D_GIC_BASE_ADDR & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
+}
+
+static int __init imx7_suspend_init(const struct imx7_pm_socdata *socdata)
+{
+ const u32 (*ddrc_offset_array)[2];
+ const u32 (*ddrc_phy_offset_array)[2];
+ unsigned long iram_paddr;
+ int i;
+
+ suspend_set_ops(&imx7_pm_ops);
+
+ if (!socdata) {
+ pr_warn("%s: invalid argument!\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * 16KB is allocated for IRAM TLB, but only up 8k is for kernel TLB,
+ * The lower 8K is not used, so use the lower 8K for IRAM code and
+ * pm_info.
+ *
+ */
+ iram_paddr = iram_tlb_phys_addr + MX7_SUSPEND_IRAM_ADDR_OFFSET;
+
+ /* Make sure iram_paddr is 8 byte aligned. */
+ if ((uintptr_t)(iram_paddr) & (FNCPY_ALIGN - 1))
+ iram_paddr += FNCPY_ALIGN - iram_paddr % (FNCPY_ALIGN);
+
+ /* Get the virtual address of the suspend code. */
+ suspend_ocram_base = (void *)IMX_IO_P2V(iram_paddr);
+
+ if (psci_ops.cpu_suspend) {
+ pm_info = kmalloc(sizeof(*pm_info), GFP_KERNEL);
+ if (!pm_info)
+ return -ENOMEM;
+ } else {
+ pm_info = suspend_ocram_base;
+ }
+ /* pbase points to iram_paddr. */
+ pm_info->pbase = iram_paddr;
+ pm_info->resume_addr = virt_to_phys(ca7_cpu_resume);
+ pm_info->pm_info_size = sizeof(*pm_info);
+
+ /*
+ * ccm physical address is not used by asm code currently,
+ * so get ccm virtual address directly, as we already have
+ * it from ccm driver.
+ */
+ pm_info->ccm_base.pbase = MX7D_CCM_BASE_ADDR;
+ pm_info->ccm_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_CCM_BASE_ADDR);
+
+ pm_info->ddrc_base.pbase = MX7D_DDRC_BASE_ADDR;
+ pm_info->ddrc_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_DDRC_BASE_ADDR);
+
+ pm_info->ddrc_phy_base.pbase = MX7D_DDRC_PHY_BASE_ADDR;
+ pm_info->ddrc_phy_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR);
+
+ pm_info->src_base.pbase = MX7D_SRC_BASE_ADDR;
+ pm_info->src_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_SRC_BASE_ADDR);
+
+ pm_info->iomuxc_gpr_base.pbase = MX7D_IOMUXC_GPR_BASE_ADDR;
+ pm_info->iomuxc_gpr_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR);
+
+ pm_info->gpc_base.pbase = MX7D_GPC_BASE_ADDR;
+ pm_info->gpc_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_GPC_BASE_ADDR);
+
+ pm_info->anatop_base.pbase = MX7D_ANATOP_BASE_ADDR;
+ pm_info->anatop_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR);
+
+ pm_info->snvs_base.pbase = MX7D_SNVS_BASE_ADDR;
+ pm_info->snvs_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_SNVS_BASE_ADDR);
+
+ pm_info->lpsr_base.pbase = MX7D_LPSR_BASE_ADDR;
+ lpsr_base = pm_info->lpsr_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_LPSR_BASE_ADDR);
+
+ pm_info->gic_base.pbase = MX7D_GIC_BASE_ADDR;
+ pm_info->gic_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_GIC_BASE_ADDR);
+
+ pm_info->ddrc_num = socdata->ddrc_num;
+ ddrc_offset_array = socdata->ddrc_offset;
+ pm_info->ddrc_phy_num = socdata->ddrc_phy_num;
+ ddrc_phy_offset_array = socdata->ddrc_phy_offset;
+
+ /* initialize DDRC settings */
+ for (i = 0; i < pm_info->ddrc_num; i++) {
+ pm_info->ddrc_val[i][0] = ddrc_offset_array[i][0];
+ if (ddrc_offset_array[i][1] == READ_DATA_FROM_HARDWARE)
+ pm_info->ddrc_val[i][1] =
+ readl_relaxed(pm_info->ddrc_base.vbase +
+ ddrc_offset_array[i][0]);
+ else
+ pm_info->ddrc_val[i][1] = ddrc_offset_array[i][1];
+
+ if (pm_info->ddrc_val[i][0] == 0xd0)
+ pm_info->ddrc_val[i][1] |= 0xc0000000;
+ }
+
+ /* initialize DDRC PHY settings */
+ for (i = 0; i < pm_info->ddrc_phy_num; i++) {
+ pm_info->ddrc_phy_val[i][0] =
+ ddrc_phy_offset_array[i][0];
+ if (ddrc_phy_offset_array[i][1] == READ_DATA_FROM_HARDWARE)
+ pm_info->ddrc_phy_val[i][1] =
+ readl_relaxed(pm_info->ddrc_phy_base.vbase +
+ ddrc_phy_offset_array[i][0]);
+ else
+ pm_info->ddrc_phy_val[i][1] =
+ ddrc_phy_offset_array[i][1];
+ }
+
+ if (psci_ops.cpu_suspend)
+ return 0;
+
+ imx7_suspend_in_ocram_fn = fncpy(
+ suspend_ocram_base + sizeof(*pm_info),
+ &imx7_suspend,
+ MX7_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
+
+ return 0;
+}
+
+static void __init imx7_pm_common_init(const struct imx7_pm_socdata
+ *socdata)
+{
+ int ret;
+ struct regmap *gpr;
+
+ if (IS_ENABLED(CONFIG_SUSPEND)) {
+ ret = imx7_suspend_init(socdata);
+ if (ret)
+ pr_warn("%s: No DDR LPM support with suspend %d!\n",
+ __func__, ret);
+ }
+
+ /*
+ * Force IOMUXC irq pending, so that the interrupt to GPC can be
+ * used to deassert dsm_request signal when the signal gets
+ * asserted unexpectedly.
+ */
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");
+ if (!IS_ERR(gpr))
+ regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_IRQ_MASK,
+ IMX7D_GPR1_IRQ_MASK);
+}
+
+void __init imx7d_pm_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ if (imx_src_is_m4_enabled()) {
+ /* map the 32K of M4 TCM */
+ np = of_find_node_by_path(
+ "/tcml@007f8000");
+ if (np)
+ lpm_m4tcm_base = of_iomap(np, 0);
+ WARN_ON(!lpm_m4tcm_base);
+
+ /* map the m4 bootrom from dtb */
+ np = of_find_node_by_path(
+ "/soc/sram@00180000");
+ if (np)
+ m4_bootrom_base = of_iomap(np, 0);
+ WARN_ON(!m4_bootrom_base);
+
+ lpm_m4tcm_saved_in_ddr = kzalloc(SZ_32K, GFP_KERNEL);
+ WARN_ON(!lpm_m4tcm_saved_in_ddr);
+
+ /* save M4 Image to DDR */
+ memcpy(lpm_m4tcm_saved_in_ddr, lpm_m4tcm_base, SZ_32K);
+ }
+ np = of_find_compatible_node(NULL, NULL, "fsl,lpm-sram");
+ if (of_get_property(np, "fsl,enable-lpsr", NULL))
+ lpsr_enabled = true;
+
+ if (psci_ops.cpu_suspend)
+ lpsr_enabled = false;
+
+ if (lpsr_enabled) {
+ pr_info("LPSR mode enabled, DSM will go into LPSR mode!\n");
+ lpm_ocram_base = of_iomap(np, 0);
+ WARN_ON(!lpm_ocram_base);
+ WARN_ON(of_address_to_resource(np, 0, &res));
+ lpm_ocram_size = resource_size(&res);
+ lpm_ocram_saved_in_ddr = kzalloc(lpm_ocram_size, GFP_KERNEL);
+ WARN_ON(!lpm_ocram_saved_in_ddr);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30000000/iomuxc@30330000");
+ if (np)
+ iomuxc_base = of_iomap(np, 0);
+ WARN_ON(!iomuxc_base);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30000000/gpt@302d0000");
+ if (np)
+ gpt1_base = of_iomap(np, 0);
+ WARN_ON(!gpt1_base);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30400000/system-counter-cmp@306b0000");
+ if (np)
+ system_counter_cmp_base = of_iomap(np, 0);
+ WARN_ON(!system_counter_cmp_base);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30000000/gpio@30200000");
+ if (np)
+ gpio1_base = of_iomap(np, 0);
+ WARN_ON(!gpio1_base);
+ }
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30400000/system-counter-ctrl@306c0000");
+ if (np)
+ system_counter_ctrl_base = of_iomap(np, 0);
+ WARN_ON(!system_counter_ctrl_base);
+
+ if (imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR3
+ || imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ imx7_pm_common_init(&imx7d_pm_data_lpddr3);
+ else if (imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_DDR3)
+ imx7_pm_common_init(&imx7d_pm_data_ddr3);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mega-fast-sram");
+ ocram_base = of_iomap(np, 0);
+ WARN_ON(!ocram_base);
+ WARN_ON(of_address_to_resource(np, 0, &res));
+ ocram_size = resource_size(&res);
+ ocram_saved_in_ddr = kzalloc(ocram_size, GFP_KERNEL);
+ WARN_ON(!ocram_saved_in_ddr);
+
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30800000/spba-bus@30800000/serial@30860000");
+ if (np)
+ console_base = of_iomap(np, 0);
+
+ /* clear LPSR resume address first */
+ imx7_pm_set_lpsr_resume_addr(0);
+}
diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c
index 7b2f7387e662..c821642317ec 100644
--- a/arch/arm/mach-imx/pm-imx7ulp.c
+++ b/arch/arm/mach-imx/pm-imx7ulp.c
@@ -5,64 +5,814 @@
* Author: Dong Aisheng <aisheng.dong@nxp.com>
*/
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/init.h>
#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/genalloc.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/psci.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/mach/map.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include <uapi/linux/psci.h>
#include "common.h"
+#include "hardware.h"
+
+#define MU_SR 0x60
+
+#define PMPROT 0x8
+#define PMCTRL 0x10
+#define PMSTAT 0x18
+#define SRS 0x20
+#define RPC 0x24
+#define SSRS 0x28
+#define SRIE 0x2c
+#define SRIF 0x30
+#define CSRE 0x34
+#define MR 0x40
+
+#define PMC1_HSRUN 0x4
+#define PMC1_RUN 0x8
+#define PMC1_VLPR 0xc
+#define PMC1_STOP 0x10
+#define PMC1_VLPS 0x14
+#define PMC1_LLS 0x18
+#define PMC1_VLLS 0x1c
+#define PMC1_STATUS 0x20
+#define PMC1_CTRL 0x24
+#define PMC0_CTRL 0x28
+
+#define BM_PMPROT_AHSRUN (1 << 7)
+#define BM_PMPROT_AVLP (1 << 5)
+#define BM_PMPROT_ALLS (1 << 3)
+#define BM_PMPROT_AVLLS (1 << 1)
+
+#define BM_PMCTRL_STOPA (1 << 24)
+#define BM_PMCTRL_PSTOPO (3 << 16)
+#define BM_PMCTRL_RUNM (3 << 8)
+#define BM_PMCTRL_STOPM (7 << 0)
+
+#define BM_VLPS_RBBEN (1 << 28)
+
+#define BM_CTRL_LDOEN (1 << 31)
+#define BM_CTRL_LDOOKDIS (1 << 30)
+
+#define BM_VLLS_MON1P2HVDHP (1 << 5)
+#define BM_VLLS_MON1P2LVDHP (1 << 4)
-#define SMC_PMCTRL 0x10
-#define BP_PMCTRL_PSTOPO 16
-#define PSTOPO_PSTOP3 0x3
-#define PSTOPO_PSTOP2 0x2
-#define PSTOPO_PSTOP1 0x1
-#define BP_PMCTRL_RUNM 8
-#define RUNM_RUN 0
#define BP_PMCTRL_STOPM 0
-#define STOPM_STOP 0
+#define BP_PMCTRL_PSTOPO 16
+
+#define MX7ULP_MAX_MMDC_IO_NUM 64
+#define MX7ULP_MAX_MMDC_NUM 50
+#define MX7ULP_MAX_IOMUX_NUM 116
+#define MX7ULP_MAX_SELECT_INPUT_NUM 78
+
+#define IOMUX_START 0x0
+#define SELECT_INPUT_START 0x200
-#define BM_PMCTRL_PSTOPO (3 << BP_PMCTRL_PSTOPO)
-#define BM_PMCTRL_RUNM (3 << BP_PMCTRL_RUNM)
-#define BM_PMCTRL_STOPM (7 << BP_PMCTRL_STOPM)
+#define TPM_SC 0x10
+#define TPM_MOD 0x18
+#define TPM_C0SC 0x20
+#define TPM_C0V 0x24
+
+#define PCC2_ENABLE_PCS_FIRC ((1 << 30) | (3 << 24))
+#define PCC2_ENABLE (1 << 30)
+
+#define LPUART_BAUD 0x10
+#define LPUART_CTRL 0x18
+#define LPUART_FIFO 0x28
+#define LPUART_WATER 0x2c
+
+#define GPIO_PDOR 0x0
+#define GPIO_PDDR 0x14
+
+#define PTC2_LPUART4_TX_OFFSET 0x8
+#define PTC3_LPUART4_RX_OFFSET 0xc
+#define PTC2_LPUART4_TX_INPUT_OFFSET 0x248
+#define PTC3_LPUART4_RX_INPUT_OFFSET 0x24c
+#define LPUART4_MUX_VALUE (4 << 8)
+#define LPUART4_INPUT_VALUE (1)
+
+#define MU_B_SR_NMIC (1 << 3)
+
+#define DGO_GPR3 0x60
+#define DGO_GPR4 0x64
+
+#define ADDR_1M_MASK 0xFFF00000
static void __iomem *smc1_base;
+static void __iomem *pmc0_base;
+static void __iomem *pmc1_base;
+static void __iomem *tpm5_base;
+static void __iomem *lpuart4_base;
+static void __iomem *iomuxc1_base;
+static void __iomem *pcc2_base;
+static void __iomem *pcc3_base;
+static void __iomem *mu_base;
+static void __iomem *scg1_base;
+static void __iomem *gpio_base[4];
+static void __iomem *suspend_ocram_base;
+static void (*imx7ulp_suspend_in_ocram_fn)(void __iomem *sram_base);
+
+static u32 tpm5_regs[4];
+static u32 lpuart4_regs[4];
+static u32 pcc2_regs[24][2] = {
+ {0x20, 0}, {0x3c, 0}, {0x40, 0}, {0x6c, 0},
+ {0x84, 0}, {0x90, 0}, {0x94, 0}, {0x98, 0},
+ {0x9c, 0}, {0xa4, 0}, {0xa8, 0}, {0xac, 0},
+ {0xb0, 0}, {0xb4, 0}, {0xb8, 0}, {0xc4, 0},
+ {0xcc, 0}, {0xd0, 0}, {0xd4, 0}, {0xd8, 0},
+ {0xdc, 0}, {0xe0, 0}, {0xf4, 0}, {0x10c, 0},
+};
+
+static u32 pcc3_regs[16][2] = {
+ {0x84, 0}, {0x88, 0}, {0x90, 0}, {0x94, 0},
+ {0x98, 0}, {0x9c, 0}, {0xa0, 0}, {0xa4, 0},
+ {0xa8, 0}, {0xac, 0}, {0xb8, 0}, {0xbc, 0},
+ {0xc0, 0}, {0xc4, 0}, {0x140, 0}, {0x144, 0},
+};
+
+static u32 scg1_offset[17] = {
+ 0x14, 0x30, 0x40, 0x304,
+ 0x500, 0x504, 0x508, 0x50c,
+ 0x510, 0x514, 0x600, 0x604,
+ 0x608, 0x60c, 0x610, 0x614,
+ 0x104,
+};
+
+extern unsigned long iram_tlb_base_addr;
+extern unsigned long iram_tlb_phys_addr;
+
+/*
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ * .
+ * .
+ * .
+ * ^
+ * ^
+ * ^
+ * imx7ulp_suspend code
+ * PM_INFO structure(imx7ulp_cpu_pm_info)
+ * ======================== low address =======================
+ */
+struct imx7ulp_pm_socdata {
+ u32 ddr_type;
+ const char *mmdc_compat;
+ const u32 mmdc_io_num;
+ const u32 *mmdc_io_offset;
+ const u32 mmdc_num;
+ const u32 *mmdc_offset;
+};
+
+static const u32 imx7ulp_mmdc_io_lpddr3_offset[] __initconst = {
+ 0x0, 0x4, 0x8, 0xc,
+ 0x10, 0x14, 0x18, 0x1c,
+ 0x20, 0x24, 0x28, 0x2c,
+ 0x30, 0x34, 0x38, 0x3c,
+ 0x40, 0x44, 0x48, 0x4c,
+ 0x50, 0x54, 0x58, 0x5c,
+ 0x60, 0x64, 0x68, 0x6c,
+ 0x70, 0x74, 0x78, 0x7c,
+ 0x80, 0x84, 0x88, 0x8c,
+ 0x90, 0x94, 0x98, 0x9c,
+ 0xa0, 0xa4, 0xa8, 0xac,
+ 0xb0, 0xb4, 0xb8, 0xbc,
+ 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xd0, 0xd4, 0xd8, 0xdc,
+ 0xe8, 0xf8, 0xfc, 0x120,
+ 0x124,
+};
+
+static const u32 imx7ulp_mmdc_lpddr3_offset[] __initconst = {
+ 0x01c, 0x800, 0x85c, 0x890,
+ 0x848, 0x850, 0x81c, 0x820,
+ 0x824, 0x828, 0x82c, 0x830,
+ 0x834, 0x838, 0x8c0, 0x8b8,
+ 0x004, 0x00c, 0x010, 0x038,
+ 0x014, 0x018, 0x02c, 0x030,
+ 0x040, 0x000, 0x01c, 0x01c,
+ 0x01c, 0x01c, 0x01c, 0x01c,
+ 0x01c, 0x01c, 0x01c, 0x01c,
+ 0x01c, 0x01c, 0x83c, 0x020,
+ 0x800, 0x004, 0x404, 0x01c,
+};
+
+static const u32 imx7ulp_lpddr3_script[] __initconst = {
+ 0x00008000, 0xA1390003, 0x0D3900A0, 0x00400000,
+ 0x40404040, 0x40404040, 0x33333333, 0x33333333,
+ 0x33333333, 0x33333333, 0xf3333333, 0xf3333333,
+ 0xf3333333, 0xf3333333, 0x24922492, 0x00000800,
+ 0x00020052, 0x292C42F3, 0x00100A22, 0x00120556,
+ 0x00C700DB, 0x00211718, 0x0F9F26D2, 0x009F0E10,
+ 0x0000003F, 0xC3190000, 0x00008050, 0x00008058,
+ 0x003F8030, 0x003F8038, 0xFF0A8030, 0xFF0A8038,
+ 0x04028030, 0x04028038, 0x83018030, 0x83018038,
+ 0x01038030, 0x01038038, 0x20000000, 0x00001800,
+ 0xA1310000, 0x00020052, 0x00011006, 0x00000000,
+};
+
+static const struct imx7ulp_pm_socdata imx7ulp_lpddr3_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx7ulp-mmdc",
+ .mmdc_io_num = ARRAY_SIZE(imx7ulp_mmdc_io_lpddr3_offset),
+ .mmdc_io_offset = imx7ulp_mmdc_io_lpddr3_offset,
+ .mmdc_num = ARRAY_SIZE(imx7ulp_mmdc_lpddr3_offset),
+ .mmdc_offset = imx7ulp_mmdc_lpddr3_offset,
+};
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * suspend code(arch/arm/mach-imx/suspend-imx7ulp.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/suspend-imx7ulp.S must be also changed accordingly,
+ * otherwise, the suspend to sram function will be broken!
+ */
+struct imx7ulp_cpu_pm_info {
+ u32 m4_reserve0;
+ u32 m4_reserve1;
+ u32 m4_reserve2;
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 pm_info_size; /* Size of pm_info. */
+ void __iomem *sim_base;
+ void __iomem *scg1_base;
+ void __iomem *mmdc_base;
+ void __iomem *mmdc_io_base;
+ void __iomem *smc1_base;
+ u32 scg1[17];
+ u32 ttbr1; /* Store TTBR1 */
+ u32 gpio[4][2];
+ u32 iomux_num; /* Number of IOs which need saved/restored. */
+ u32 iomux_val[MX7ULP_MAX_IOMUX_NUM]; /* To save value */
+ u32 select_input_num; /* Number of select input which need saved/restored. */
+ u32 select_input_val[MX7ULP_MAX_SELECT_INPUT_NUM]; /* To save value */
+ u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
+ u32 mmdc_io_val[MX7ULP_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+ u32 mmdc_num; /* Number of MMDC registers which need saved/restored. */
+ u32 mmdc_val[MX7ULP_MAX_MMDC_NUM][2];
+} __aligned(8);
+
+static struct imx7ulp_cpu_pm_info *pm_info;
+static void __iomem *aips1_base;
+static void __iomem *aips2_base;
+static void __iomem *aips3_base;
+static void __iomem *aips4_base;
+static void __iomem *aips5_base;
+
+static const char * const low_power_ocram_match[] __initconst = {
+ "fsl,lpm-sram",
+ NULL
+};
+
+static void imx7ulp_gpio_save(void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ pm_info->gpio[i][0] = readl_relaxed(gpio_base[i] + GPIO_PDOR);
+ pm_info->gpio[i][1] = readl_relaxed(gpio_base[i] + GPIO_PDDR);
+ }
+}
+
+static void imx7ulp_scg1_save(void)
+{
+ int i;
+
+ for (i = 0; i < 17; i++)
+ pm_info->scg1[i] = readl_relaxed(scg1_base + scg1_offset[i]);
+}
+
+static void imx7ulp_pcc3_save(void)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ pcc3_regs[i][1] = readl_relaxed(pcc3_base + pcc3_regs[i][0]);
+}
+
+static void imx7ulp_pcc3_restore(void)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ writel_relaxed(pcc3_regs[i][1], pcc3_base + pcc3_regs[i][0]);
+}
+
+static void imx7ulp_pcc2_save(void)
+{
+ int i;
+
+ for (i = 0; i < 24; i++)
+ pcc2_regs[i][1] = readl_relaxed(pcc2_base + pcc2_regs[i][0]);
+}
+
+static void imx7ulp_pcc2_restore(void)
+{
+ int i;
+
+ for (i = 0; i < 24; i++)
+ writel_relaxed(pcc2_regs[i][1], pcc2_base + pcc2_regs[i][0]);
+}
+
+static inline void imx7ulp_iomuxc_save(void)
+{
+ int i;
+
+ pm_info->iomux_num = MX7ULP_MAX_IOMUX_NUM;
+ pm_info->select_input_num = MX7ULP_MAX_SELECT_INPUT_NUM;
+
+ for (i = 0; i < pm_info->iomux_num; i++)
+ pm_info->iomux_val[i] =
+ readl_relaxed(iomuxc1_base +
+ IOMUX_START + i * 0x4);
+ for (i = 0; i < pm_info->select_input_num; i++)
+ pm_info->select_input_val[i] =
+ readl_relaxed(iomuxc1_base +
+ SELECT_INPUT_START + i * 0x4);
+}
+
+static void imx7ulp_lpuart_save(void)
+{
+ lpuart4_regs[0] = readl_relaxed(lpuart4_base + LPUART_BAUD);
+ lpuart4_regs[1] = readl_relaxed(lpuart4_base + LPUART_FIFO);
+ lpuart4_regs[2] = readl_relaxed(lpuart4_base + LPUART_WATER);
+ lpuart4_regs[3] = readl_relaxed(lpuart4_base + LPUART_CTRL);
+}
+
+static void imx7ulp_lpuart_restore(void)
+{
+ writel_relaxed(LPUART4_MUX_VALUE,
+ iomuxc1_base + PTC2_LPUART4_TX_OFFSET);
+ writel_relaxed(LPUART4_MUX_VALUE,
+ iomuxc1_base + PTC3_LPUART4_RX_OFFSET);
+ writel_relaxed(LPUART4_INPUT_VALUE,
+ iomuxc1_base + PTC2_LPUART4_TX_INPUT_OFFSET);
+ writel_relaxed(LPUART4_INPUT_VALUE,
+ iomuxc1_base + PTC3_LPUART4_RX_INPUT_OFFSET);
+
+ writel_relaxed(lpuart4_regs[0], lpuart4_base + LPUART_BAUD);
+ writel_relaxed(lpuart4_regs[1], lpuart4_base + LPUART_FIFO);
+ writel_relaxed(lpuart4_regs[2], lpuart4_base + LPUART_WATER);
+ writel_relaxed(lpuart4_regs[3], lpuart4_base + LPUART_CTRL);
+}
+
+static void imx7ulp_tpm_save(void)
+{
+ tpm5_regs[0] = readl_relaxed(tpm5_base + TPM_SC);
+ tpm5_regs[1] = readl_relaxed(tpm5_base + TPM_MOD);
+ tpm5_regs[2] = readl_relaxed(tpm5_base + TPM_C0SC);
+ tpm5_regs[3] = readl_relaxed(tpm5_base + TPM_C0V);
+}
+
+static void imx7ulp_tpm_restore(void)
+{
+ writel_relaxed(tpm5_regs[0], tpm5_base + TPM_SC);
+ writel_relaxed(tpm5_regs[1], tpm5_base + TPM_MOD);
+ writel_relaxed(tpm5_regs[2], tpm5_base + TPM_C0SC);
+ writel_relaxed(tpm5_regs[3], tpm5_base + TPM_C0V);
+}
+
+static void imx7ulp_set_dgo(u32 val)
+{
+ writel_relaxed(val, pm_info->sim_base + DGO_GPR3);
+ writel_relaxed(val, pm_info->sim_base + DGO_GPR4);
+}
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
{
- u32 val = readl_relaxed(smc1_base + SMC_PMCTRL);
+ u32 val1 = BM_PMPROT_AHSRUN | BM_PMPROT_AVLP | BM_PMPROT_AVLLS;
+ u32 val2 = readl_relaxed(smc1_base + PMCTRL);
+ u32 val3 = readl_relaxed(pmc0_base + PMC0_CTRL);
- /* clear all */
- val &= ~(BM_PMCTRL_RUNM | BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO);
+ val2 &= ~(BM_PMCTRL_RUNM |
+ BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO);
+ val3 |= BM_CTRL_LDOOKDIS;
switch (mode) {
case ULP_PM_RUN:
/* system/bus clock enabled */
- val |= PSTOPO_PSTOP3 << BP_PMCTRL_PSTOPO;
+ val2 |= 0x3 << BP_PMCTRL_PSTOPO;
break;
case ULP_PM_WAIT:
/* system clock disabled, bus clock enabled */
- val |= PSTOPO_PSTOP2 << BP_PMCTRL_PSTOPO;
+ val2 |= 0x2 << BP_PMCTRL_PSTOPO;
break;
case ULP_PM_STOP:
/* system/bus clock disabled */
- val |= PSTOPO_PSTOP1 << BP_PMCTRL_PSTOPO;
+ val2 |= 0x1 << BP_PMCTRL_PSTOPO;
+ break;
+ case ULP_PM_VLPS:
+ val2 |= 0x2 << BP_PMCTRL_STOPM;
+ break;
+ case ULP_PM_VLLS:
+ val2 |= 0x4 << BP_PMCTRL_STOPM;
break;
default:
return -EINVAL;
}
- writel_relaxed(val, smc1_base + SMC_PMCTRL);
+ writel_relaxed(val1, smc1_base + PMPROT);
+ writel_relaxed(val2, smc1_base + PMCTRL);
+ writel_relaxed(val3, pmc0_base + PMC0_CTRL);
return 0;
}
-void __init imx7ulp_pm_init(void)
+#define MX7ULP_SUSPEND_POWERDWN_PARAM \
+ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+#define MX7ULP_SUSPEND_STANDBY_PARAM \
+ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
+ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
+ (PSCI_POWER_STATE_TYPE_STANDBY << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
+
+static int imx7ulp_suspend_finish(unsigned long val)
+{
+ u32 state;
+
+ if (val == 0)
+ state = MX7ULP_SUSPEND_POWERDWN_PARAM;
+ else
+ state = MX7ULP_SUSPEND_STANDBY_PARAM;
+
+ if (psci_ops.cpu_suspend)
+ return psci_ops.cpu_suspend(state, __pa(cpu_resume));
+
+ imx7ulp_suspend_in_ocram_fn(suspend_ocram_base);
+
+ return 0;
+}
+
+static int imx7ulp_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ if (psci_ops.cpu_suspend)
+ /* Zzz ... */
+ cpu_suspend(1, imx7ulp_suspend_finish);
+ else {
+ imx7ulp_set_lpm(ULP_PM_VLPS);
+ writel_relaxed(
+ readl_relaxed(pmc1_base + PMC1_VLPS) | BM_VLPS_RBBEN,
+ pmc1_base + PMC1_VLPS);
+
+ /* Zzz ... */
+ cpu_suspend(0, imx7ulp_suspend_finish);
+
+ writel_relaxed(
+ readl_relaxed(pmc1_base + PMC1_VLPS) & ~BM_VLPS_RBBEN,
+ pmc1_base + PMC1_VLPS);
+ imx7ulp_set_lpm(ULP_PM_RUN);
+ }
+ break;
+ case PM_SUSPEND_MEM:
+ if (psci_ops.cpu_suspend) {
+ /* Zzz ... */
+ cpu_suspend(0, imx7ulp_suspend_finish);
+ } else {
+ imx7ulp_gpio_save();
+ imx7ulp_scg1_save();
+ imx7ulp_pcc2_save();
+ imx7ulp_pcc3_save();
+ imx7ulp_tpm_save();
+ if (!console_suspend_enabled)
+ imx7ulp_lpuart_save();
+ imx7ulp_iomuxc_save();
+ imx7ulp_set_lpm(ULP_PM_VLLS);
+
+ /* Zzz ... */
+ cpu_suspend(0, imx7ulp_suspend_finish);
+
+ imx7ulp_pcc2_restore();
+ imx7ulp_pcc3_restore();
+ if (!console_suspend_enabled)
+ imx7ulp_lpuart_restore();
+ imx7ulp_set_dgo(0);
+ imx7ulp_tpm_restore();
+ imx7ulp_set_lpm(ULP_PM_RUN);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Put CA7 into VLLS mode before M4 power off CA7 */
+void imx7ulp_poweroff(void)
+{
+ imx7ulp_set_lpm(ULP_PM_VLLS);
+ cpu_suspend(0, imx7ulp_suspend_finish);
+}
+
+static int imx7ulp_pm_valid(suspend_state_t state)
+{
+ return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
+}
+
+static const struct platform_suspend_ops imx7ulp_pm_ops = {
+ .enter = imx7ulp_pm_enter,
+ .valid = imx7ulp_pm_valid,
+};
+
+static int __init imx7ulp_suspend_init(void)
+{
+ int ret = 0;
+
+ suspend_set_ops(&imx7ulp_pm_ops);
+
+ return ret;
+}
+
+static struct map_desc iram_tlb_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_1M,
+ .type = MT_MEMORY_RWX_NONCACHED,
+};
+
+static int __init imx7ulp_dt_find_lpsram(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ unsigned long lpram_addr;
+ const __be32 *prop = of_get_flat_dt_prop(node, "reg", NULL);
+
+ if (of_flat_dt_match(node, low_power_ocram_match)) {
+ if (!prop)
+ return -EINVAL;
+
+ lpram_addr = be32_to_cpup(prop);
+
+ /* We need to create a 1M page table entry. */
+ iram_tlb_io_desc.virtual =
+ IMX_IO_P2V(lpram_addr & ADDR_1M_MASK);
+ iram_tlb_io_desc.pfn = __phys_to_pfn(lpram_addr & ADDR_1M_MASK);
+ iram_tlb_phys_addr = lpram_addr;
+ iram_tlb_base_addr = IMX_IO_P2V(lpram_addr);
+ iotable_init(&iram_tlb_io_desc, 1);
+ }
+
+ return 0;
+}
+
+void __init imx7ulp_pm_map_io(void)
+{
+ /*
+ * Get the address of IRAM or OCRAM to be used by the low
+ * power code from the device tree.
+ */
+ WARN_ON(of_scan_flat_dt(imx7ulp_dt_find_lpsram, NULL));
+
+ /* Return if no IRAM space is allocated for suspend/resume code. */
+ if (!iram_tlb_base_addr) {
+ pr_warn("No valid ocram available for suspend/resume!\n");
+ return;
+ }
+}
+
+void __init imx7ulp_pm_common_init(const struct imx7ulp_pm_socdata
+ *socdata)
{
struct device_node *np;
+ unsigned long sram_paddr = 0;
+ const u32 *mmdc_offset_array;
+ const u32 *mmdc_io_offset_array;
+ unsigned long i, j;
+ int ret;
+
+ if (psci_ops.cpu_suspend) {
+ aips1_base = ioremap(MX7ULP_AIPS1_BASE_ADDR, SZ_1M);
+ aips2_base = ioremap(MX7ULP_AIPS2_BASE_ADDR, SZ_1M);
+ aips3_base = ioremap(MX7ULP_AIPS3_BASE_ADDR, SZ_1M);
+ aips4_base = ioremap(MX7ULP_AIPS4_BASE_ADDR, SZ_1M);
+ aips5_base = ioremap(MX7ULP_AIPS5_BASE_ADDR, SZ_1M);
+ } else {
+ /* Set all entries to 0 except first 3 words reserved for M4. */
+ memset((void *)iram_tlb_base_addr, 0, MX7ULP_IRAM_TLB_SIZE);
+
+ /*
+ * Make sure the IRAM virtual address has a mapping in the IRAM
+ * page table.
+ *
+ * Only use the top 12 bits [31-20] when storing the physical
+ * address in the page table as only these bits are required
+ * for 1M mapping.
+ */
+ j = ((iram_tlb_base_addr >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ (iram_tlb_phys_addr & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ /*
+ * Make sure the AIPS1 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ aips1_base = ioremap(MX7ULP_AIPS1_BASE_ADDR, SZ_1M);
+ j = (((u32)aips1_base >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7ULP_AIPS1_BASE_ADDR) & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ /*
+ * Make sure the AIPS2 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ aips2_base = ioremap(MX7ULP_AIPS2_BASE_ADDR, SZ_1M);
+ j = (((u32)aips2_base >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7ULP_AIPS2_BASE_ADDR) & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ /*
+ * Make sure the AIPS3 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ aips3_base = ioremap(MX7ULP_AIPS3_BASE_ADDR, SZ_1M);
+ j = (((u32)aips3_base >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7ULP_AIPS3_BASE_ADDR) & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ /*
+ * Make sure the AIPS4 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ aips4_base = ioremap(MX7ULP_AIPS4_BASE_ADDR, SZ_1M);
+ j = (((u32)aips4_base >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7ULP_AIPS4_BASE_ADDR) & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ /*
+ * Make sure the AIPS5 virtual address has a mapping in the
+ * IRAM page table.
+ */
+ aips5_base = ioremap(MX7ULP_AIPS5_BASE_ADDR, SZ_1M);
+ j = (((u32)aips5_base >> 20) << 2) / 4;
+ *((unsigned long *)iram_tlb_base_addr + j) =
+ ((MX7ULP_AIPS5_BASE_ADDR) & ADDR_1M_MASK) |
+ TT_ATTRIB_NON_CACHEABLE_1M;
+ }
np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1");
smc1_base = of_iomap(np, 0);
WARN_ON(!smc1_base);
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pmc0");
+ pmc0_base = of_iomap(np, 0);
+ WARN_ON(!pmc0_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pmc1");
+ pmc1_base = of_iomap(np, 0);
+ WARN_ON(!pmc1_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-tpm");
+ tpm5_base = of_iomap(np, 0);
+ WARN_ON(!tpm5_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-lpuart");
+ lpuart4_base = of_iomap(np, 0);
+ WARN_ON(!lpuart4_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc2");
+ pcc2_base = of_iomap(np, 0);
+ WARN_ON(!pcc2_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc3");
+ pcc3_base = of_iomap(np, 0);
+ WARN_ON(!pcc3_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-iomuxc1");
+ iomuxc1_base = of_iomap(np, 0);
+ WARN_ON(!iomuxc1_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-scg1");
+ scg1_base = of_iomap(np, 0);
+ WARN_ON(!scg1_base);
+
+ np = NULL;
+ for (i = 0; i < 4; i++) {
+ np = of_find_compatible_node(np, NULL, "fsl,vf610-gpio");
+ gpio_base[i] = of_iomap(np, 1);
+ WARN_ON(!gpio_base[i]);
+ }
+
+ if (psci_ops.cpu_suspend) {
+ pm_info = kzalloc(SZ_16K, GFP_KERNEL);
+ if (!pm_info)
+ panic("pm info allocation failed\n");
+ } else {
+ /*
+ * 16KB is allocated for IRAM TLB, but only up 8k is for kernel TLB,
+ * The lower 8K is not used, so use the lower 8K for IRAM code and
+ * pm_info.
+ *
+ */
+ sram_paddr = iram_tlb_phys_addr;
+
+ /* Make sure sram_paddr is 8 byte aligned. */
+ if ((uintptr_t)(sram_paddr) & (FNCPY_ALIGN - 1))
+ sram_paddr += FNCPY_ALIGN - sram_paddr % (FNCPY_ALIGN);
+
+ /* Get the virtual address of the suspend code. */
+ suspend_ocram_base = (void *)IMX_IO_P2V(sram_paddr);
+
+ pm_info = suspend_ocram_base;
+ }
+ pm_info->pbase = sram_paddr;
+ pm_info->resume_addr = virt_to_phys(imx7ulp_cpu_resume);
+ pm_info->pm_info_size = sizeof(*pm_info);
+
+ pm_info->scg1_base = aips2_base +
+ (MX7ULP_SCG1_BASE_ADDR & ~ADDR_1M_MASK);
+ pm_info->smc1_base = aips3_base +
+ (MX7ULP_SMC1_BASE_ADDR & ~ADDR_1M_MASK);
+ pm_info->mmdc_base = aips4_base +
+ (MX7ULP_MMDC_BASE_ADDR & ~ADDR_1M_MASK);
+ pm_info->mmdc_io_base = aips4_base +
+ (MX7ULP_MMDC_IO_BASE_ADDR & ~ADDR_1M_MASK);
+ pm_info->sim_base = aips5_base +
+ (MX7ULP_SIM_BASE_ADDR & ~ADDR_1M_MASK);
+
+ pm_info->mmdc_io_num = socdata->mmdc_io_num;
+ mmdc_io_offset_array = socdata->mmdc_io_offset;
+ pm_info->mmdc_num = socdata->mmdc_num;
+ mmdc_offset_array = socdata->mmdc_offset;
+
+ for (i = 0; i < pm_info->mmdc_io_num; i++) {
+ pm_info->mmdc_io_val[i][0] =
+ mmdc_io_offset_array[i];
+ pm_info->mmdc_io_val[i][1] =
+ readl_relaxed(pm_info->mmdc_io_base +
+ mmdc_io_offset_array[i]);
+ }
+
+ /* initialize MMDC settings */
+ for (i = 0; i < pm_info->mmdc_num; i++)
+ pm_info->mmdc_val[i][0] =
+ mmdc_offset_array[i];
+
+ for (i = 0; i < pm_info->mmdc_num; i++)
+ pm_info->mmdc_val[i][1] = imx7ulp_lpddr3_script[i];
+
+ if (!psci_ops.cpu_suspend) {
+ imx7ulp_suspend_in_ocram_fn = fncpy(
+ suspend_ocram_base + sizeof(*pm_info),
+ &imx7ulp_suspend,
+ MX7ULP_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
+ }
+
+ if (IS_ENABLED(CONFIG_SUSPEND)) {
+ ret = imx7ulp_suspend_init();
+ if (ret)
+ pr_warn("%s: No DDR LPM support with suspend %d!\n",
+ __func__, ret);
+ }
+}
+
+void __init imx7ulp_pm_init(void)
+{
+ imx7ulp_pm_common_init(&imx7ulp_lpddr3_pm_data);
imx7ulp_set_lpm(ULP_PM_RUN);
}
+
+static irqreturn_t imx7ulp_nmi_isr(int irq, void *param)
+{
+ writel_relaxed(readl_relaxed(mu_base + MU_SR) | MU_B_SR_NMIC,
+ mu_base + MU_SR);
+ pm_system_wakeup();
+
+ return IRQ_HANDLED;
+}
+
+void imx7ulp_enable_nmi(void)
+{
+ struct device_node *np;
+ int irq, ret;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-nmi");
+ mu_base = of_iomap(np, 0);
+ WARN_ON(!mu_base);
+ irq = of_irq_get(np, 0);
+ ret = request_irq(irq, imx7ulp_nmi_isr,
+ IRQF_NO_SUSPEND, "imx7ulp-nmi", NULL);
+ if (ret) {
+ pr_err("%s: register interrupt %d failed, rc %d\n",
+ __func__, irq, ret);
+ return;
+ }
+}
diff --git a/arch/arm/mach-imx/pm-rpmsg.c b/arch/arm/mach-imx/pm-rpmsg.c
new file mode 100644
index 000000000000..4dfe489f5d38
--- /dev/null
+++ b/arch/arm/mach-imx/pm-rpmsg.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2017-2018 NXP
+ *
+ * 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/err.h>
+#include <linux/slab.h>
+#include <linux/imx_rpmsg.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/reboot.h>
+#include <linux/rpmsg.h>
+#include <linux/uaccess.h>
+#include <linux/virtio.h>
+#include "common.h"
+
+#define RPMSG_TIMEOUT 1000
+
+#define PM_RPMSG_TYPE 0
+#define HEATBEAT_RPMSG_TYPE 2
+
+enum pm_rpmsg_cmd {
+ PM_RPMSG_MODE,
+ PM_RPMSG_HEART_BEAT,
+ PM_RPMSG_HEART_BEAT_OFF,
+};
+
+enum pm_rpmsg_power_mode {
+ PM_RPMSG_HSRUN,
+ PM_RPMSG_RUN,
+ PM_RPMSG_VLPR,
+ PM_RPMSG_WAIT,
+ PM_RPMSG_VLPS,
+ PM_RPMSG_VLLS,
+ PM_RPMSG_REBOOT,
+ PM_RPMSG_SHUTDOWN,
+};
+
+struct pm_rpmsg_info {
+ struct rpmsg_device *rpdev;
+ struct device *dev;
+ struct pm_rpmsg_data *msg;
+ struct pm_qos_request pm_qos_req;
+ struct notifier_block restart_handler;
+ struct completion cmd_complete;
+ bool first_flag;
+ struct mutex lock;
+};
+
+static struct pm_rpmsg_info pm_rpmsg;
+
+static struct delayed_work heart_beat_work;
+
+static bool heartbeat_off;
+
+struct pm_rpmsg_data {
+ struct imx_rpmsg_head header;
+ u8 data;
+} __attribute__ ((packed));
+
+static int pm_send_message(struct pm_rpmsg_data *msg,
+ struct pm_rpmsg_info *info, bool ack)
+{
+ int err;
+
+ if (!info->rpdev) {
+ dev_dbg(info->dev,
+ "rpmsg channel not ready, m4 image ready?\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&info->lock);
+ pm_qos_add_request(&info->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
+ reinit_completion(&info->cmd_complete);
+
+ err = rpmsg_send(info->rpdev->ept, (void *)msg,
+ sizeof(struct pm_rpmsg_data));
+
+ if (err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err);
+ goto err_out;
+ }
+
+ if (ack) {
+ err = wait_for_completion_timeout(&info->cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+ if (!err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send timeout!\n");
+ err = -ETIMEDOUT;
+ goto err_out;
+ }
+
+ if (info->msg->data != 0) {
+ dev_err(&info->rpdev->dev, "rpmsg not ack %d!\n",
+ info->msg->data);
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ err = 0;
+ }
+
+err_out:
+ pm_qos_remove_request(&info->pm_qos_req);
+ mutex_unlock(&info->lock);
+
+ return err;
+}
+
+static int pm_vlls_notify_m4(bool enter)
+{
+ struct pm_rpmsg_data msg;
+
+ msg.header.cate = IMX_RMPSG_LIFECYCLE;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = PM_RPMSG_TYPE;
+ msg.header.cmd = PM_RPMSG_MODE;
+ msg.data = enter ? PM_RPMSG_VLLS : PM_RPMSG_RUN;
+
+ return pm_send_message(&msg, &pm_rpmsg, true);
+}
+
+void pm_shutdown_notify_m4(void)
+{
+ struct pm_rpmsg_data msg;
+
+ msg.header.cate = IMX_RMPSG_LIFECYCLE;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = PM_RPMSG_TYPE;
+ msg.header.cmd = PM_RPMSG_MODE;
+ msg.data = PM_RPMSG_SHUTDOWN;
+ /* No ACK from M4 */
+ pm_send_message(&msg, &pm_rpmsg, false);
+ imx7ulp_poweroff();
+}
+
+void pm_reboot_notify_m4(void)
+{
+ struct pm_rpmsg_data msg;
+
+ msg.header.cate = IMX_RMPSG_LIFECYCLE;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = PM_RPMSG_TYPE;
+ msg.header.cmd = PM_RPMSG_MODE;
+ msg.data = PM_RPMSG_REBOOT;
+
+ pm_send_message(&msg, &pm_rpmsg, true);
+
+}
+
+void pm_heartbeat_off_notify_m4(bool enter)
+{
+ struct pm_rpmsg_data msg;
+
+ msg.header.cate = IMX_RMPSG_LIFECYCLE;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = PM_RPMSG_TYPE;
+ msg.header.cmd = PM_RPMSG_HEART_BEAT_OFF;
+ msg.data = enter ? 0 : 1;
+
+ pm_send_message(&msg, &pm_rpmsg, true);
+}
+
+static void pm_heart_beat_work_handler(struct work_struct *work)
+{
+ struct pm_rpmsg_data msg;
+
+ /* Notify M4 side A7 in RUN mode at boot time */
+ if (pm_rpmsg.first_flag) {
+ pm_vlls_notify_m4(false);
+
+ pm_heartbeat_off_notify_m4(heartbeat_off);
+
+ pm_rpmsg.first_flag = false;
+ }
+
+ if (!heartbeat_off) {
+ msg.header.cate = IMX_RMPSG_LIFECYCLE;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = HEATBEAT_RPMSG_TYPE;
+ msg.header.cmd = PM_RPMSG_HEART_BEAT;
+ msg.data = 0;
+ pm_send_message(&msg, &pm_rpmsg, false);
+
+ schedule_delayed_work(&heart_beat_work,
+ msecs_to_jiffies(30000));
+ }
+}
+
+static void pm_poweroff_rpmsg(void)
+{
+ pm_shutdown_notify_m4();
+ pr_emerg("Unable to poweroff system\n");
+}
+
+static int pm_restart_handler(struct notifier_block *this, unsigned long mode,
+ void *cmd)
+{
+ pm_reboot_notify_m4();
+
+ return NOTIFY_DONE;
+}
+
+static int pm_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ int ret;
+
+ pm_rpmsg.rpdev = rpdev;
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ init_completion(&pm_rpmsg.cmd_complete);
+ mutex_init(&pm_rpmsg.lock);
+
+ INIT_DELAYED_WORK(&heart_beat_work,
+ pm_heart_beat_work_handler);
+
+ pm_rpmsg.first_flag = true;
+ schedule_delayed_work(&heart_beat_work, 0);
+
+ pm_rpmsg.restart_handler.notifier_call = pm_restart_handler;
+ pm_rpmsg.restart_handler.priority = 128;
+ ret = register_restart_handler(&pm_rpmsg.restart_handler);
+ if (ret)
+ dev_err(&rpdev->dev, "cannot register restart handler\n");
+
+ pm_power_off = pm_poweroff_rpmsg;
+
+ return 0;
+}
+
+static int pm_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+ struct pm_rpmsg_data *msg = (struct pm_rpmsg_data *)data;
+
+ pm_rpmsg.msg = msg;
+
+ complete(&pm_rpmsg.cmd_complete);
+
+ return 0;
+}
+
+static void pm_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "pm rpmsg driver is removed\n");
+}
+
+static struct rpmsg_device_id pm_rpmsg_id_table[] = {
+ { .name = "rpmsg-life-cycle-channel" },
+ { },
+};
+
+static struct rpmsg_driver pm_rpmsg_driver = {
+ .drv.name = "pm_rpmsg",
+ .drv.owner = THIS_MODULE,
+ .id_table = pm_rpmsg_id_table,
+ .probe = pm_rpmsg_probe,
+ .callback = pm_rpmsg_cb,
+ .remove = pm_rpmsg_remove,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int pm_heartbeat_suspend(struct device *dev)
+{
+ int err;
+
+ err = pm_vlls_notify_m4(true);
+ if (err)
+ return err;
+
+ cancel_delayed_work_sync(&heart_beat_work);
+
+ return 0;
+}
+
+static int pm_heartbeat_resume(struct device *dev)
+{
+ int err;
+
+ err = pm_vlls_notify_m4(false);
+ if (err)
+ return err;
+
+ schedule_delayed_work(&heart_beat_work,
+ msecs_to_jiffies(10000));
+
+ return 0;
+}
+#endif
+
+static int pm_heartbeat_probe(struct platform_device *pdev)
+{
+ platform_set_drvdata(pdev, &pm_rpmsg);
+
+ return register_rpmsg_driver(&pm_rpmsg_driver);
+}
+
+static const struct of_device_id pm_heartbeat_id[] = {
+ {"fsl,heartbeat-rpmsg",},
+ {},
+};
+MODULE_DEVICE_TABLE(of, pm_heartbeat_id);
+
+static const struct dev_pm_ops pm_heartbeat_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_heartbeat_suspend,
+ pm_heartbeat_resume)
+};
+
+static struct platform_driver pm_heartbeat_driver = {
+ .driver = {
+ .name = "heartbeat-rpmsg",
+ .owner = THIS_MODULE,
+ .of_match_table = pm_heartbeat_id,
+ .pm = &pm_heartbeat_ops,
+ },
+ .probe = pm_heartbeat_probe,
+};
+
+static int __init setup_heartbeat(char *str)
+{
+ heartbeat_off = true;
+
+ return 1;
+};
+__setup("heartbeat_off", setup_heartbeat);
+
+module_platform_driver(pm_heartbeat_driver);
+
+MODULE_DESCRIPTION("Freescale PM rpmsg driver");
+MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-imx/smp_wfe.S b/arch/arm/mach-imx/smp_wfe.S
new file mode 100644
index 000000000000..08894bb39c4d
--- /dev/null
+++ b/arch/arm/mach-imx/smp_wfe.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include <asm/smp_scu.h>
+#include "hardware.h"
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+#ifdef CONFIG_SMP
+ .align 3
+
+ENTRY(imx7_smp_wfe)
+ push {r4 - r11, lr}
+
+ dsb
+ isb
+
+ disable_l1_dcache
+
+ isb
+
+ /* Turn off SMP bit. */
+ mrc p15, 0, r8, c1, c0, 1
+ bic r8, r8, #0x40
+ mcr p15, 0, r8, c1, c0, 1
+
+ isb
+ /* Set flag of entering WFE. */
+ mov r7, #0xff
+ lsl r7, r7, r0
+ mov r6, #SCU_PM_DORMANT
+ lsl r6, r6, r0
+ ldr r8, [r1, #0x4]
+ bic r8, r8, r7
+ orr r6, r6, r8
+ str r6, [r1, #0x4]
+
+go_back_wfe:
+ wfe
+
+ /* Offset 0x0 stores busfeq done flag */
+ ldr r6, [r1]
+ cmp r6, #1
+ beq go_back_wfe
+
+ /* Turn ON SMP bit. */
+ mrc p15, 0, r8, c1, c0, 1
+ orr r8, r8, #0x40
+ mcr p15, 0, r8, c1, c0, 1
+
+ isb
+ /* Enable L1 data cache. */
+ mrc p15, 0, r8, c1, c0, 0
+ orr r8, r8, #0x4
+ mcr p15, 0, r8, c1, c0, 0
+ isb
+
+ /* Set flag of exiting WFE. */
+ mov r7, #0xff
+ lsl r7, r7, r0
+ mov r6, #SCU_PM_NORMAL
+ lsl r6, r6, r0
+ ldr r8, [r1, #0x4]
+ bic r8, r8, r7
+ orr r6, r6, r8
+ str r6, [r1, #0x4]
+
+ /* Pop all saved registers. */
+ pop {r4 - r11, lr}
+ mov pc, lr
+ .ltorg
+ENDPROC(imx7_smp_wfe)
+#endif
diff --git a/arch/arm/mach-imx/smp_wfe_imx6.S b/arch/arm/mach-imx/smp_wfe_imx6.S
new file mode 100644
index 000000000000..791e93ce98da
--- /dev/null
+++ b/arch/arm/mach-imx/smp_wfe_imx6.S
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/linkage.h>
+#include <asm/smp_scu.h>
+#include "hardware.h"
+
+#ifdef CONFIG_SMP
+.extern scu_base
+#endif
+
+.globl wfe_smp_freq_change_start
+.globl wfe_smp_freq_change_end
+
+#ifdef CONFIG_SMP
+
+ .align 3
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r11, lr}
+
+ ldr r7, =v7_flush_kern_cache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r11, lr}
+
+ .endm
+
+ENTRY(wfe_smp_freq_change)
+wfe_smp_freq_change_start:
+ push {r4 - r11, lr}
+
+ mov r6, r0
+ mov r7, r1
+
+ dsb
+ isb
+
+ disable_l1_dcache
+
+ isb
+
+ /* Turn off SMP bit. */
+ mrc p15, 0, r8, c1, c0, 1
+ bic r8, r8, #0x40
+ mcr p15, 0, r8, c1, c0, 1
+
+ isb
+
+ /* Inform the SCU we are going to enter WFE. */
+ push {r0 - r11, lr}
+
+ ldr r0,=scu_base
+ ldr r0, [r0]
+ mov r1, #SCU_PM_DORMANT
+ ldr r3, =scu_power_mode
+ mov lr, pc
+ mov pc, r3
+
+ pop {r0 - r11, lr}
+
+go_back_wfe:
+ wfe
+
+ ldr r3, [r7]
+ cmp r3, #1
+ beq go_back_wfe
+
+ /* Turn ON SMP bit. */
+ mrc p15, 0, r8, c1, c0, 1
+ orr r8, r8, #0x40
+ mcr p15, 0, r8, c1, c0, 1
+
+ isb
+ /* Enable L1 data cache. */
+ mrc p15, 0, r8, c1, c0, 0
+ orr r8, r8, #0x4
+ mcr p15, 0, r8, c1, c0, 0
+ isb
+
+ /* Inform the SCU we have exited WFE. */
+ push {r0 - r11, lr}
+
+ ldr r0,=scu_base
+ ldr r0, [r0]
+ mov r1, #SCU_PM_NORMAL
+ ldr r3, =scu_power_mode
+ mov lr, pc
+ mov pc, r3
+
+ pop {r0 - r11, lr}
+
+ /* Pop all saved registers. */
+ pop {r4 - r11, lr}
+ mov pc, lr
+ .ltorg
+wfe_smp_freq_change_end:
+ENDPROC(wfe_smp_freq_change)
+
+#ifdef CONFIG_OPTEE
+/**
+ * @brief Switch CPU in WFE mode while bus frequency change
+ * on-going
+ *
+ * @param[in] r0 CPU in WFE Status
+ * @param[in] r1 Bus frequency change status
+ */
+
+.globl imx_smp_wfe_optee_end
+
+ENTRY(imx_smp_wfe_optee)
+ push {r4-r11, lr}
+
+ dsb
+ isb
+
+ disable_l1_dcache
+ isb
+
+ /* Set flag CPU entering WFE. */
+ mov r4, #1
+ str r4, [r0]
+
+ dsb
+ isb
+
+1:
+ wfe
+
+ /* Check if busfreq is done, else loop */
+ ldr r4, [r1]
+ cmp r4, #1
+ beq 1b
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r4, c1, c0, 0
+ orr r4, r4, #0x4
+ mcr p15, 0, r4, c1, c0, 0
+ isb
+
+ /* Set flag CPU exiting WFE. */
+ mov r4, #0
+ str r4, [r0]
+
+ /* Pop all saved registers. */
+ pop {r4-r11, lr}
+ mov pc, lr
+ .ltorg
+imx_smp_wfe_optee_end:
+ENDPROC(imx_smp_wfe_optee)
+#endif
+#endif
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 0beea6d0217f..399771e2912e 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -12,6 +12,7 @@
#include <linux/smp.h>
#include <asm/smp_plat.h>
#include "common.h"
+#include "hardware.h"
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
@@ -23,9 +24,18 @@
#define BP_SRC_SCR_SW_IPU2_RST 12
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
+/* below is for i.MX7D */
+#define SRC_GPR1_V2 0x074
+#define SRC_A7RCR0 0x004
+#define SRC_A7RCR1 0x008
+#define SRC_M4RCR 0x00C
+
+#define BP_SRC_A7RCR0_A7_CORE_RESET0 0
+#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
static void __iomem *src_base;
-static DEFINE_SPINLOCK(scr_lock);
+static DEFINE_SPINLOCK(src_lock);
+static bool m4_is_enabled;
static const int sw_reset_bits[5] = {
BP_SRC_SCR_SW_GPU_RST,
@@ -35,6 +45,11 @@ static const int sw_reset_bits[5] = {
BP_SRC_SCR_SW_IPU2_RST
};
+bool imx_src_is_m4_enabled(void)
+{
+ return m4_is_enabled;
+}
+
static int imx_src_reset_module(struct reset_controller_dev *rcdev,
unsigned long sw_reset_idx)
{
@@ -51,11 +66,11 @@ static int imx_src_reset_module(struct reset_controller_dev *rcdev,
bit = 1 << sw_reset_bits[sw_reset_idx];
- spin_lock_irqsave(&scr_lock, flags);
+ spin_lock_irqsave(&src_lock, flags);
val = readl_relaxed(src_base + SRC_SCR);
val |= bit;
writel_relaxed(val, src_base + SRC_SCR);
- spin_unlock_irqrestore(&scr_lock, flags);
+ spin_unlock_irqrestore(&src_lock, flags);
timeout = jiffies + msecs_to_jiffies(1000);
while (readl(src_base + SRC_SCR) & bit) {
@@ -81,32 +96,59 @@ void imx_enable_cpu(int cpu, bool enable)
u32 mask, val;
cpu = cpu_logical_map(cpu);
- mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
- spin_lock(&scr_lock);
- val = readl_relaxed(src_base + SRC_SCR);
- val = enable ? val | mask : val & ~mask;
- val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
- writel_relaxed(val, src_base + SRC_SCR);
- spin_unlock(&scr_lock);
+ spin_lock(&src_lock);
+ if (cpu_is_imx7d()) {
+ /* enable core */
+ if (enable)
+ imx_gpcv2_set_core1_pdn_pup_by_software(false);
+
+ mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_A7RCR1);
+ val = enable ? val | mask : val & ~mask;
+ writel_relaxed(val, src_base + SRC_A7RCR1);
+ } else {
+ mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_SCR);
+ val = enable ? val | mask : val & ~mask;
+ val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
+ writel_relaxed(val, src_base + SRC_SCR);
+ }
+ spin_unlock(&src_lock);
}
void imx_set_cpu_jump(int cpu, void *jump_addr)
{
+ spin_lock(&src_lock);
cpu = cpu_logical_map(cpu);
- writel_relaxed(__pa_symbol(jump_addr),
- src_base + SRC_GPR1 + cpu * 8);
+ if (cpu_is_imx7d())
+ writel_relaxed(__pa_symbol(jump_addr),
+ src_base + SRC_GPR1_V2 + cpu * 8);
+ else
+ writel_relaxed(__pa_symbol(jump_addr),
+ src_base + SRC_GPR1 + cpu * 8);
+ spin_unlock(&src_lock);
}
u32 imx_get_cpu_arg(int cpu)
{
cpu = cpu_logical_map(cpu);
- return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+ if (cpu_is_imx7d())
+ return readl_relaxed(src_base + SRC_GPR1_V2
+ + cpu * 8 + 4);
+ else
+ return readl_relaxed(src_base + SRC_GPR1
+ + cpu * 8 + 4);
}
void imx_set_cpu_arg(int cpu, u32 arg)
{
cpu = cpu_logical_map(cpu);
- writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+ if (cpu_is_imx7d())
+ writel_relaxed(arg, src_base + SRC_GPR1_V2
+ + cpu * 8 + 4);
+ else
+ writel_relaxed(arg, src_base + SRC_GPR1
+ + cpu * 8 + 4);
}
void __init imx_src_init(void)
@@ -120,6 +162,15 @@ void __init imx_src_init(void)
src_base = of_iomap(np, 0);
WARN_ON(!src_base);
+ if (cpu_is_imx7d()) {
+ val = readl_relaxed(src_base + SRC_M4RCR);
+ if (((val & BIT(3)) == BIT(3)) && !(val & BIT(0)))
+ m4_is_enabled = true;
+ else
+ m4_is_enabled = false;
+ return;
+ }
+
imx_reset_controller.of_node = np;
if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
reset_controller_register(&imx_reset_controller);
@@ -128,9 +179,17 @@ void __init imx_src_init(void)
* force warm reset sources to generate cold reset
* for a more reliable restart
*/
- spin_lock(&scr_lock);
+ spin_lock(&src_lock);
val = readl_relaxed(src_base + SRC_SCR);
+
+ /* bit 4 is m4c_non_sclr_rst on i.MX6SX */
+ if (cpu_is_imx6sx() && ((val &
+ (1 << BP_SRC_SCR_SW_OPEN_VG_RST)) == 0))
+ m4_is_enabled = true;
+ else
+ m4_is_enabled = false;
+
val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
writel_relaxed(val, src_base + SRC_SCR);
- spin_unlock(&scr_lock);
+ spin_unlock(&src_lock);
}
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index 1eabf2d2834b..a7e349e583e7 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -41,23 +41,32 @@
#define PM_INFO_RESUME_ADDR_OFFSET 0x4
#define PM_INFO_DDR_TYPE_OFFSET 0x8
#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC
-#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
-#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
-#define PM_INFO_MX6Q_SRC_P_OFFSET 0x18
-#define PM_INFO_MX6Q_SRC_V_OFFSET 0x1C
-#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x20
-#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x24
-#define PM_INFO_MX6Q_CCM_P_OFFSET 0x28
-#define PM_INFO_MX6Q_CCM_V_OFFSET 0x2C
-#define PM_INFO_MX6Q_GPC_P_OFFSET 0x30
-#define PM_INFO_MX6Q_GPC_V_OFFSET 0x34
-#define PM_INFO_MX6Q_L2_P_OFFSET 0x38
-#define PM_INFO_MX6Q_L2_V_OFFSET 0x3C
-#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40
-#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44
+#define PM_INFO_MX6Q_MMDC0_P_OFFSET 0x10
+#define PM_INFO_MX6Q_MMDC0_V_OFFSET 0x14
+#define PM_INFO_MX6Q_MMDC1_P_OFFSET 0x18
+#define PM_INFO_MX6Q_MMDC1_V_OFFSET 0x1C
+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x20
+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x24
+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x28
+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x2C
+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x30
+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x34
+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x38
+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x3C
+#define PM_INFO_MX6Q_L2_P_OFFSET 0x40
+#define PM_INFO_MX6Q_L2_V_OFFSET 0x44
+#define PM_INFO_MX6Q_ANATOP_P_OFFSET 0x48
+#define PM_INFO_MX6Q_ANATOP_V_OFFSET 0x4C
+#define PM_INFO_MX6Q_TTBR1_V_OFFSET 0x50
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x54
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x58
+/* below offsets depends on MX6_MAX_MMDC_IO_NUM(36) definition */
+#define PM_INFO_MMDC_NUM_OFFSET 0x208
+#define PM_INFO_MMDC_VAL_OFFSET 0x20C
#define MX6Q_SRC_GPR1 0x20
#define MX6Q_SRC_GPR2 0x24
+#define MX6Q_MMDC_MISC 0x18
#define MX6Q_MMDC_MAPSR 0x404
#define MX6Q_MMDC_MPDGCTRL0 0x83c
#define MX6Q_GPC_IMR1 0x08
@@ -65,9 +74,49 @@
#define MX6Q_GPC_IMR3 0x10
#define MX6Q_GPC_IMR4 0x14
#define MX6Q_CCM_CCR 0x0
+#define MX6Q_ANATOP_CORE 0x140
.align 3
+ /* Check if the cpu is cortex-a7 */
+ .macro is_cortex_a7
+
+ /* Read the primary cpu number is MPIDR */
+ mrc p15, 0, r5, c0, c0, 0
+ ldr r6, =0xfff0
+ and r5, r5, r6
+ ldr r6, =0xc070
+ cmp r5, r6
+
+ .endm
+
+ .macro disable_l1_cache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 -r10, lr}
+ ldr r7, = v7_flush_dcache_all
+ mov lr, pc
+ mov pc , r7
+ pop {r0 -r10, lr}
+
+ .endm
+
.macro sync_l2_cache
/* sync L2 cache to drain L2's buffers to DRAM. */
@@ -86,29 +135,8 @@
.endm
- .macro resume_mmdc
-
- /* restore MMDC IO */
- cmp r5, #0x0
- ldreq r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- ldrne r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
-
- ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
- ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
- add r7, r7, r0
-1:
- ldr r8, [r7], #0x4
- ldr r9, [r7], #0x4
- str r9, [r11, r8]
- subs r6, r6, #0x1
- bne 1b
-
- cmp r5, #0x0
- ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
- ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
-
- cmp r3, #IMX_DDR_TYPE_LPDDR2
- bne 4f
+ /* r11 must be MMDC base address */
+ .macro reset_read_fifo
/* reset read FIFO, RST_RD_FIFO */
ldr r7, =MX6Q_MMDC_MPDGCTRL0
@@ -128,23 +156,294 @@
ldr r6, [r11, r7]
ands r6, r6, #(1 << 31)
bne 3b
+
+ /* check if lppdr2 2 channel mode is enabled */
+ ldr r7, =MX6Q_MMDC_MISC
+ ldr r6, [r11, r7]
+ ands r6, r6, #(1 << 2)
+ beq 6f
+
+ ldr r7, =MX6Q_MMDC_MPDGCTRL0
+ ldr r6, [r12, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r12, r7]
4:
+ ldr r6, [r12, r7]
+ ands r6, r6, #(1 << 31)
+ bne 4b
+
+ ldr r6, [r12, r7]
+ orr r6, r6, #(1 << 31)
+ str r6, [r12, r7]
+5:
+ ldr r6, [r12, r7]
+ ands r6, r6, #(1 << 31)
+ bne 5b
+
+6:
+ .endm
+
+ /* r11 must be MMDC base address */
+ .macro mmdc_out_and_auto_self_refresh
+
/* let DDR out of self-refresh */
ldr r7, [r11, #MX6Q_MMDC_MAPSR]
bic r7, r7, #(1 << 21)
str r7, [r11, #MX6Q_MMDC_MAPSR]
-5:
+7:
ldr r7, [r11, #MX6Q_MMDC_MAPSR]
ands r7, r7, #(1 << 25)
- bne 5b
+ bne 7b
/* enable DDR auto power saving */
ldr r7, [r11, #MX6Q_MMDC_MAPSR]
bic r7, r7, #0x1
str r7, [r11, #MX6Q_MMDC_MAPSR]
+ /* check if lppdr2 2 channel mode is enabled */
+ ldr r7, =MX6Q_MMDC_MISC
+ ldr r6, [r11, r7]
+ ands r6, r6, #(1 << 2)
+ beq 9f
+
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 21)
+ str r7, [r12, #MX6Q_MMDC_MAPSR]
+8:
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ bne 8b
+
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r12, #MX6Q_MMDC_MAPSR]
+9:
+ .endm
+
+ /* r10 must be iomuxc base address */
+ .macro resume_iomuxc_gpr
+
+ add r10, r10, #0x4000
+ /* IOMUXC GPR DRAM_RESET_BYPASS */
+ ldr r4, [r10, #0x8]
+ bic r4, r4, #(0x1 << 27)
+ str r4, [r10, #0x8]
+ /* IOMUXC GPR DRAM_CKE_BYPASS */
+ ldr r4, [r10, #0x8]
+ bic r4, r4, #(0x1 << 31)
+ str r4, [r10, #0x8]
+
+ .endm
+
+ .macro resume_io
+
+ /* restore MMDC IO */
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+10:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x8
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 10b
+
+ cmp r5, #0x0
+ /* Here only MMDC0 is set */
+ ldreq r11, [r0, #PM_INFO_MX6Q_MMDC0_V_OFFSET]
+ ldrne r11, [r0, #PM_INFO_MX6Q_MMDC0_P_OFFSET]
+ ldreq r12, [r0, #PM_INFO_MX6Q_MMDC1_V_OFFSET]
+ ldrne r12, [r0, #PM_INFO_MX6Q_MMDC1_P_OFFSET]
+
+ reset_read_fifo
+ mmdc_out_and_auto_self_refresh
+
+ .endm
+
+ .macro resume_mmdc_io
+
+ cmp r5, #0x0
+ ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
+ ldreq r11, [r0, #PM_INFO_MX6Q_MMDC0_V_OFFSET]
+ ldrne r11, [r0, #PM_INFO_MX6Q_MMDC0_P_OFFSET]
+
+ /* resume mmdc iomuxc settings */
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+11:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x8
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 11b
+
+ /* check whether we need to restore MMDC */
+ cmp r5, #0x0
+ beq 12f
+
+ /* check whether last suspend is with M/F mix off */
+ ldr r9, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
+ ldr r6, [r9, #0x220]
+ cmp r6, #0x0
+ bne 13f
+12:
+ resume_iomuxc_gpr
+ reset_read_fifo
+
+ b 17f
+13:
+ /* restore MMDC settings */
+ ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_VAL_OFFSET
+ add r7, r7, r0
+14:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r11, r8]
+ subs r6, r6, #0x1
+ bne 14b
+
+ /* let DDR enter self-refresh */
+ ldr r7, [r11, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 20)
+ str r7, [r11, #MX6Q_MMDC_MAPSR]
+15:
+ ldr r7, [r11, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ beq 15b
+
+ resume_iomuxc_gpr
+ reset_read_fifo
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r11, #MX6Q_MMDC_MAPSR]
+ bic r7, r7, #(1 << 20)
+ str r7, [r11, #MX6Q_MMDC_MAPSR]
+16:
+ ldr r7, [r11, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ bne 16b
+
+ /* kick off MMDC */
+ ldr r4, =0x0
+ str r4, [r11, #0x1c]
+
+17:
+ mmdc_out_and_auto_self_refresh
+
+ .endm
+
+ .macro store_ttbr1
+
+ /* Store TTBR1 to pm_info->ttbr1 */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_MX6Q_TTBR1_V_OFFSET]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r6, [r6]
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r6, c2, c0, 1
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Disable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ is_cortex_a7
+ beq 17f
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r8, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+ mov r6, #0x0
+ str r6, [r8, #0x100]
+
+ dsb
+ isb
+#endif
+17:
.endm
+ .macro restore_ttbr1
+
+ is_cortex_a7
+ beq 18f
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Enable L2. */
+ ldr r8, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+ ldr r7, =0x1
+ str r7, [r8, #0x100]
+#endif
+
+18:
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Restore TTBCR */
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Restore TTBR1, get the origin ttbr1 from pm info */
+ ldr r7, [r0, #PM_INFO_MX6Q_TTBR1_V_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+
ENTRY(imx6_suspend)
ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
@@ -179,10 +478,25 @@ ENTRY(imx6_suspend)
str r9, [r11, #MX6Q_SRC_GPR1]
str r1, [r11, #MX6Q_SRC_GPR2]
+ /*
+ * Check if the cpu is Cortex-A7, for Cortex-A7
+ * the cache implementation is not the same as
+ * Cortex-A9, so the cache maintenance operation
+ * is different.
+ */
+ is_cortex_a7
+ beq a7_dache_flush
+
/* need to sync L2 cache before DSM. */
sync_l2_cache
-
- ldr r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
+ b ttbr_store
+a7_dache_flush:
+ disable_l1_cache
+ttbr_store:
+ store_ttbr1
+
+ ldr r11, [r0, #PM_INFO_MX6Q_MMDC0_V_OFFSET]
+ ldr r12, [r0, #PM_INFO_MX6Q_MMDC1_V_OFFSET]
/*
* put DDR explicitly into self-refresh and
* disable automatic power savings.
@@ -201,31 +515,59 @@ poll_dvfs_set:
ands r7, r7, #(1 << 25)
beq poll_dvfs_set
+ /* check if lppdr2 2 channel mode is enabled */
+ ldr r7, =MX6Q_MMDC_MISC
+ ldr r6, [r11, r7]
+ ands r6, r6, #(1 << 2)
+ beq skip_self_refresh_ch1
+
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r12, #MX6Q_MMDC_MAPSR]
+
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ orr r7, r7, #(1 << 21)
+ str r7, [r12, #MX6Q_MMDC_MAPSR]
+
+poll_dvfs_set_ch1:
+ ldr r7, [r12, #MX6Q_MMDC_MAPSR]
+ ands r7, r7, #(1 << 25)
+ beq poll_dvfs_set_ch1
+
+skip_self_refresh_ch1:
+ /* use r11 to store the IO address */
ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- ldr r6, =0x0
- ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
add r8, r8, r0
- /* LPDDR2's last 3 IOs need special setting */
- cmp r3, #IMX_DDR_TYPE_LPDDR2
- subeq r7, r7, #0x3
set_mmdc_io_lpm:
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- subs r7, r7, #0x1
+ ldr r7, [r8], #0x8
+ ldr r9, [r8], #0x4
+ str r9, [r11, r7]
+ subs r6, r6, #0x1
bne set_mmdc_io_lpm
- cmp r3, #IMX_DDR_TYPE_LPDDR2
- bne set_mmdc_io_lpm_done
- ldr r6, =0x1000
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- ldr r6, =0x80000
- ldr r9, [r8]
- str r6, [r11, r9]
-set_mmdc_io_lpm_done:
+ /* check whether it supports Mega/Fast off */
+ ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET]
+ cmp r6, #0x0
+ beq set_mmdc_lpm_done
+
+ /* IOMUXC GPR DRAM_RESET */
+ add r11, r11, #0x4000
+ ldr r6, [r11, #0x8]
+ orr r6, r6, #(0x1 << 28)
+ str r6, [r11, #0x8]
+
+ /* IOMUXC GPR DRAM_RESET_BYPASS */
+ ldr r6, [r11, #0x8]
+ orr r6, r6, #(0x1 << 27)
+ str r6, [r11, #0x8]
+
+ /* IOMUXC GPR DRAM_CKE_BYPASS */
+ ldr r6, [r11, #0x8]
+ orr r6, r6, #(0x1 << 31)
+ str r6, [r11, #0x8]
+set_mmdc_lpm_done:
/*
* mask all GPC interrupts before
@@ -285,6 +627,27 @@ rbc_loop:
subs r6, r6, #0x1
bne rbc_loop
+ /*
+ * ERR005852 Analog: Transition from Deep Sleep Mode to
+ * LDO Bypass Mode may cause the slow response of the
+ * VDDARM_CAP output.
+ *
+ * Software workaround:
+ * if internal ldo(VDDARM) bypassed, switch to analog bypass
+ * mode (0x1E), prio to entering DSM, and then, revert to the
+ * normal bypass mode, when exiting from DSM.
+ */
+ ldr r11, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
+ ldr r10, [r11, #MX6Q_ANATOP_CORE]
+ and r10, r10, #0x1f
+ cmp r10, #0x1f
+ bne ldo_check_done1
+ldo_analog_bypass:
+ ldr r10, [r11, #MX6Q_ANATOP_CORE]
+ bic r10, r10, #0x1f
+ orr r10, r10, #0x1e
+ str r10, [r11, #MX6Q_ANATOP_CORE]
+ldo_check_done1:
/* Zzz, enter stop mode */
wfi
nop
@@ -297,8 +660,28 @@ rbc_loop:
* wakeup source, system should auto
* resume, we need to restore MMDC IO first
*/
+ /* restore it with 0x1f if use ldo bypass mode.*/
+ ldr r10, [r11, #MX6Q_ANATOP_CORE]
+ and r10, r10, #0x1f
+ cmp r10, #0x1e
+ bne ldo_check_done2
+ldo_bypass_restore:
+ ldr r10, [r11, #MX6Q_ANATOP_CORE]
+ orr r10, r10, #0x1f
+ str r10, [r11, #MX6Q_ANATOP_CORE]
+ldo_check_done2:
mov r5, #0x0
- resume_mmdc
+ /* check whether it supports Mega/Fast off */
+ ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET]
+ cmp r6, #0x0
+ beq only_resume_io
+ resume_mmdc_io
+ b resume_mmdc_done
+only_resume_io:
+ resume_io
+resume_mmdc_done:
+
+ restore_ttbr1
/* return to suspend finish */
ret lr
@@ -313,6 +696,16 @@ resume:
mcr p15, 0, r6, c1, c0, 0
isb
+ /* restore it with 0x1f if use ldo bypass mode.*/
+ ldr r11, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
+ ldr r7, [r11, #MX6Q_ANATOP_CORE]
+ and r7, r7, #0x1f
+ cmp r7, #0x1e
+ bne ldo_check_done3
+ ldr r7, [r11, #MX6Q_ANATOP_CORE]
+ orr r7, r7, #0x1f
+ str r7, [r11, #MX6Q_ANATOP_CORE]
+ldo_check_done3:
/* get physical resume address from pm_info. */
ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
/* clear core0's entry and parameter */
@@ -323,7 +716,16 @@ resume:
ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
mov r5, #0x1
- resume_mmdc
+ /* check whether it supports Mega/Fast off */
+ ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET]
+ cmp r6, #0x0
+ beq dsm_only_resume_io
+ resume_mmdc_io
+ b dsm_resume_mmdc_done
+dsm_only_resume_io:
+ ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
+ resume_io
+dsm_resume_mmdc_done:
ret lr
ENDPROC(imx6_suspend)
diff --git a/arch/arm/mach-imx/suspend-imx7.S b/arch/arm/mach-imx/suspend-imx7.S
new file mode 100644
index 000000000000..5f4e31152a69
--- /dev/null
+++ b/arch/arm/mach-imx/suspend-imx7.S
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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/linkage.h>
+#include <asm/asm-offsets.h>
+#include "hardware.h"
+
+/*
+ * ==================== low level suspend ====================
+ *
+ * Better to follow below rules to use ARM registers:
+ * r0: pm_info structure address;
+ * r1 ~ r4: for saving pm_info members;
+ * r5 ~ r10: free registers;
+ * r11: io base address.
+ *
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ * .
+ * .
+ * .
+ * ^
+ * ^
+ * ^
+ * imx7_suspend code
+ * PM_INFO structure(imx7_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+/*
+ * Below offsets are based on struct imx7_cpu_pm_info
+ * which defined in arch/arm/mach-imx/pm-imx7.c, this
+ * structure contains necessary pm info for low level
+ * suspend related code.
+ */
+#define PM_INFO_M4_RESERVE0_OFFSET 0x0
+#define PM_INFO_M4_RESERVE1_OFFSET 0x4
+#define PM_INFO_M4_RESERVE2_OFFSET 0x8
+#define PM_INFO_PBASE_OFFSET 0xc
+#define PM_INFO_RESUME_ADDR_OFFSET 0x10
+#define PM_INFO_DDR_TYPE_OFFSET 0x14
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x18
+#define PM_INFO_MX7_DDRC_P_OFFSET 0x1c
+#define PM_INFO_MX7_DDRC_V_OFFSET 0x20
+#define PM_INFO_MX7_DDRC_PHY_P_OFFSET 0x24
+#define PM_INFO_MX7_DDRC_PHY_V_OFFSET 0x28
+#define PM_INFO_MX7_SRC_P_OFFSET 0x2c
+#define PM_INFO_MX7_SRC_V_OFFSET 0x30
+#define PM_INFO_MX7_IOMUXC_GPR_P_OFFSET 0x34
+#define PM_INFO_MX7_IOMUXC_GPR_V_OFFSET 0x38
+#define PM_INFO_MX7_CCM_P_OFFSET 0x3c
+#define PM_INFO_MX7_CCM_V_OFFSET 0x40
+#define PM_INFO_MX7_GPC_P_OFFSET 0x44
+#define PM_INFO_MX7_GPC_V_OFFSET 0x48
+#define PM_INFO_MX7_SNVS_P_OFFSET 0x4c
+#define PM_INFO_MX7_SNVS_V_OFFSET 0x50
+#define PM_INFO_MX7_ANATOP_P_OFFSET 0x54
+#define PM_INFO_MX7_ANATOP_V_OFFSET 0x58
+#define PM_INFO_MX7_LPSR_P_OFFSET 0x5c
+#define PM_INFO_MX7_LPSR_V_OFFSET 0x60
+#define PM_INFO_MX7_GIC_DIST_P_OFFSET 0x64
+#define PM_INFO_MX7_GIC_DIST_V_OFFSET 0x68
+#define PM_INFO_MX7_TTBR1_V_OFFSET 0x6c
+#define PM_INFO_DDRC_REG_NUM_OFFSET 0x70
+#define PM_INFO_DDRC_REG_OFFSET 0x74
+#define PM_INFO_DDRC_VALUE_OFFSET 0x78
+#define PM_INFO_DDRC_PHY_REG_NUM_OFFSET 0x174
+#define PM_INFO_DDRC_PHY_REG_OFFSET 0x178
+#define PM_INFO_DDRC_PHY_VALUE_OFFSET 0x17c
+
+#define MX7_SRC_GPR1 0x74
+#define MX7_SRC_GPR2 0x78
+#define GPC_PGC_C0 0x800
+#define GPC_PGC_FM 0xa00
+#define ANADIG_SNVS_MISC_CTRL 0x380
+#define ANADIG_SNVS_MISC_CTRL_SET 0x384
+#define ANADIG_SNVS_MISC_CTRL_CLR 0x388
+#define ANADIG_DIGPROG 0x800
+#define DDRC_STAT 0x4
+#define DDRC_PWRCTL 0x30
+#define DDRC_PSTAT 0x3fc
+#define DDRC_PCTRL_0 0x490
+#define DDRC_DFIMISC 0x1b0
+#define DDRC_SWCTL 0x320
+#define DDRC_SWSTAT 0x324
+#define DDRPHY_LP_CON0 0x18
+
+#define CCM_SNVS_LPCG 0x250
+#define MX7D_GPC_IMR1 0x30
+#define MX7D_GPC_IMR2 0x34
+#define MX7D_GPC_IMR3 0x38
+#define MX7D_GPC_IMR4 0x3c
+
+ .align 3
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro store_ttbr1
+
+ /* Store TTBR1 to pm_info->ttbr1 */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_MX7_TTBR1_V_OFFSET]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r6, [r6]
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r6, c2, c0, 1
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro restore_ttbr1
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Restore TTBCR */
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Restore TTBR1, get the origin ttbr1 from pm info */
+ ldr r7, [r0, #PM_INFO_MX7_TTBR1_V_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+ .macro ddrc_enter_self_refresh
+
+ ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFFSET]
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r11, #DDRC_PWRCTL]
+
+ /* wait rw port_busy clear */
+ ldr r6, =(0x1 << 16)
+ orr r6, r6, #0x1
+1:
+ ldr r7, [r11, #DDRC_PSTAT]
+ ands r7, r7, r6
+ bne 1b
+
+ /* enter self-refresh bit 5 */
+ ldr r7, =(0x1 << 5)
+ str r7, [r11, #DDRC_PWRCTL]
+
+ /* wait until self-refresh mode entered */
+2:
+ ldr r7, [r11, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ bne 2b
+3:
+ ldr r7, [r11, #DDRC_STAT]
+ ands r7, r7, #0x20
+ beq 3b
+
+ /* disable dram clk */
+ ldr r7, [r11, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 3)
+ str r7, [r11, #DDRC_PWRCTL]
+
+ .endm
+
+ .macro ddrc_exit_self_refresh
+
+ cmp r5, #0x0
+ ldreq r11, [r0, #PM_INFO_MX7_DDRC_V_OFFSET]
+ ldrne r11, [r0, #PM_INFO_MX7_DDRC_P_OFFSET]
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r11, #DDRC_PWRCTL]
+
+ /* wait until self-refresh mode entered */
+4:
+ ldr r7, [r11, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ beq 4b
+
+ /* enable auto self-refresh */
+ ldr r7, [r11, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r11, #DDRC_PWRCTL]
+
+ .endm
+
+ .macro wait_delay
+5:
+ subs r6, r6, #0x1
+ bne 5b
+
+ .endm
+
+ .macro ddr_enter_retention
+
+ ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFFSET]
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r11, #DDRC_PCTRL_0]
+
+ /* wait rw port_busy clear */
+ ldr r6, =(0x1 << 16)
+ orr r6, r6, #0x1
+6:
+ ldr r7, [r11, #DDRC_PSTAT]
+ ands r7, r7, r6
+ bne 6b
+
+ ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFFSET]
+ /* enter self-refresh bit 5 */
+ ldr r7, =(0x1 << 5)
+ str r7, [r11, #DDRC_PWRCTL]
+
+ /* wait until self-refresh mode entered */
+7:
+ ldr r7, [r11, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ bne 7b
+8:
+ ldr r7, [r11, #DDRC_STAT]
+ ands r7, r7, #0x20
+ beq 8b
+
+ /* disable dram clk */
+ ldr r7, =(0x1 << 5)
+ orr r7, r7, #(1 << 3)
+ str r7, [r11, #DDRC_PWRCTL]
+
+ ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFFSET]
+ ldr r7, [r11, #ANADIG_DIGPROG]
+ and r7, r7, #0xff
+ cmp r7, #0x11
+ bne 10f
+
+ /* TO 1.1 */
+ ldr r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFFSET]
+ ldr r7, =0x38000000
+ str r7, [r11]
+
+ /* LPSR mode need to use TO1.0 flow as IOMUX lost power */
+ ldr r10, [r0, #PM_INFO_MX7_LPSR_V_OFFSET]
+ ldr r7, [r10]
+ cmp r7, #0x0
+ beq 11f
+10:
+ /* reset ddr_phy */
+ ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFFSET]
+ ldr r7, =0x0
+ str r7, [r11, #ANADIG_SNVS_MISC_CTRL]
+
+ /* delay 7 us */
+ ldr r6, =6000
+ wait_delay
+
+ ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFFSET]
+ ldr r6, =0x1000
+ ldr r7, [r11, r6]
+ orr r7, r7, #0x1
+ str r7, [r11, r6]
+11:
+ /* turn off ddr power */
+ ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFFSET]
+ ldr r7, =(0x1 << 29)
+ str r7, [r11, #ANADIG_SNVS_MISC_CTRL_SET]
+
+ ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFFSET]
+ ldr r6, =0x1000
+ ldr r7, [r11, r6]
+ orr r7, r7, #0x1
+ str r7, [r11, r6]
+
+ .endm
+
+ .macro ddr_exit_retention
+
+ cmp r5, #0x0
+ ldreq r1, [r0, #PM_INFO_MX7_ANATOP_V_OFFSET]
+ ldrne r1, [r0, #PM_INFO_MX7_ANATOP_P_OFFSET]
+ ldreq r2, [r0, #PM_INFO_MX7_SRC_V_OFFSET]
+ ldrne r2, [r0, #PM_INFO_MX7_SRC_P_OFFSET]
+ ldreq r3, [r0, #PM_INFO_MX7_DDRC_V_OFFSET]
+ ldrne r3, [r0, #PM_INFO_MX7_DDRC_P_OFFSET]
+ ldreq r4, [r0, #PM_INFO_MX7_DDRC_PHY_V_OFFSET]
+ ldrne r4, [r0, #PM_INFO_MX7_DDRC_PHY_P_OFFSET]
+ ldreq r10, [r0, #PM_INFO_MX7_CCM_V_OFFSET]
+ ldrne r10, [r0, #PM_INFO_MX7_CCM_P_OFFSET]
+ ldreq r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFFSET]
+ ldrne r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_P_OFFSET]
+
+ /* turn on ddr power */
+ ldr r7, =(0x1 << 29)
+ str r7, [r1, #ANADIG_SNVS_MISC_CTRL_CLR]
+
+ ldr r6, =50
+ wait_delay
+
+ /* clear ddr_phy reset */
+ ldr r6, =0x1000
+ ldr r7, [r2, r6]
+ orr r7, r7, #0x3
+ str r7, [r2, r6]
+ ldr r7, [r2, r6]
+ bic r7, r7, #0x1
+ str r7, [r2, r6]
+13:
+ ldr r6, [r0, #PM_INFO_DDRC_REG_NUM_OFFSET]
+ ldr r7, =PM_INFO_DDRC_REG_OFFSET
+ add r7, r7, r0
+14:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r3, r8]
+ subs r6, r6, #0x1
+ bne 14b
+ ldr r7, =0x20
+ str r7, [r3, #DDRC_PWRCTL]
+ ldr r7, =0x0
+ str r7, [r3, #DDRC_DFIMISC]
+
+ /* do PHY, clear ddr_phy reset */
+ ldr r6, =0x1000
+ ldr r7, [r2, r6]
+ bic r7, r7, #0x2
+ str r7, [r2, r6]
+
+ ldr r7, [r1, #ANADIG_DIGPROG]
+ and r7, r7, #0xff
+ cmp r7, #0x11
+ bne 12f
+
+ /*
+ * TKT262940:
+ * System hang when press RST for DDR PAD is
+ * in retention mode, fixed on TO1.1
+ */
+ ldr r7, [r11]
+ bic r7, r7, #(1 << 27)
+ str r7, [r11]
+ ldr r7, [r11]
+ bic r7, r7, #(1 << 29)
+ str r7, [r11]
+12:
+ ldr r7, =(0x1 << 30)
+ str r7, [r1, #ANADIG_SNVS_MISC_CTRL_SET]
+
+ /* need to delay ~5mS */
+ ldr r6, =0x100000
+ wait_delay
+
+ ldr r6, [r0, #PM_INFO_DDRC_PHY_REG_NUM_OFFSET]
+ ldr r7, =PM_INFO_DDRC_PHY_REG_OFFSET
+ add r7, r7, r0
+
+15:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r4, r8]
+ subs r6, r6, #0x1
+ bne 15b
+
+ ldr r7, =0x0
+ add r9, r10, #0x4000
+ str r7, [r9, #0x130]
+
+ ldr r7, =0x170
+ orr r7, r7, #0x8
+ str r7, [r11, #0x20]
+
+ ldr r7, =0x2
+ add r9, r10, #0x4000
+ str r7, [r9, #0x130]
+
+ ldr r7, =0xf
+ str r7, [r4, #DDRPHY_LP_CON0]
+
+ /* wait until self-refresh mode entered */
+16:
+ ldr r7, [r3, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x3
+ bne 16b
+ ldr r7, =0x0
+ str r7, [r3, #DDRC_SWCTL]
+ ldr r7, =0x1
+ str r7, [r3, #DDRC_DFIMISC]
+ ldr r7, =0x1
+ str r7, [r3, #DDRC_SWCTL]
+17:
+ ldr r7, [r3, #DDRC_SWSTAT]
+ and r7, r7, #0x1
+ cmp r7, #0x1
+ bne 17b
+18:
+ ldr r7, [r3, #DDRC_STAT]
+ and r7, r7, #0x20
+ cmp r7, #0x20
+ bne 18b
+
+ /* let DDR out of self-refresh */
+ ldr r7, =0x0
+ str r7, [r3, #DDRC_PWRCTL]
+19:
+ ldr r7, [r3, #DDRC_STAT]
+ and r7, r7, #0x30
+ cmp r7, #0x0
+ bne 19b
+
+20:
+ ldr r7, [r3, #DDRC_STAT]
+ and r7, r7, #0x3
+ cmp r7, #0x1
+ bne 20b
+
+ /* enable port */
+ ldr r7, =0x1
+ str r7, [r3, #DDRC_PCTRL_0]
+
+ /* enable auto self-refresh */
+ ldr r7, [r3, #DDRC_PWRCTL]
+ orr r7, r7, #(1 << 0)
+ str r7, [r3, #DDRC_PWRCTL]
+
+ .endm
+
+ENTRY(imx7_suspend)
+ push {r4-r12}
+
+ /* make sure SNVS clk is enabled */
+ ldr r11, [r0, #PM_INFO_MX7_CCM_V_OFFSET]
+ add r11, r11, #0x4000
+ ldr r7, =0x3
+ str r7, [r11, #CCM_SNVS_LPCG]
+
+ /* check whether it is a standby mode */
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r7, [r11, #GPC_PGC_C0]
+ cmp r7, #0
+ beq ddr_only_self_refresh
+
+ /*
+ * The value of r0 is mapped the same in origin table and IRAM table,
+ * thus no need to care r0 here.
+ */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
+ ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r6, =imx7_suspend
+ ldr r7, =resume
+ sub r7, r7, r6
+ add r8, r1, r4
+ add r9, r8, r7
+
+ ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFFSET]
+ /* store physical resume addr and pm_info address. */
+ str r9, [r11, #MX7_SRC_GPR1]
+ str r1, [r11, #MX7_SRC_GPR2]
+
+ disable_l1_dcache
+
+ store_ttbr1
+
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r7, [r11, #GPC_PGC_FM]
+ cmp r7, #0
+ beq ddr_only_self_refresh
+
+ ddr_enter_retention
+ /* enter LPSR mode if resume addr is valid */
+ ldr r11, [r0, #PM_INFO_MX7_LPSR_V_OFFSET]
+ ldr r7, [r11]
+ cmp r7, #0x0
+ beq ddr_retention_enter_out
+
+ /* disable STOP mode before entering LPSR */
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r7, [r11]
+ bic r7, #0xf
+ str r7, [r11]
+
+ /* shut down vddsoc to enter lpsr mode */
+ ldr r11, [r0, #PM_INFO_MX7_SNVS_V_OFFSET]
+ ldr r7, [r11, #0x38]
+ orr r7, r7, #0x60
+ str r7, [r11, #0x38]
+wait_shutdown:
+ wfi
+ nop
+ nop
+ nop
+ nop
+ b wait_shutdown
+
+ddr_only_self_refresh:
+ ddrc_enter_self_refresh
+ b wfi
+ddr_retention_enter_out:
+
+ ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFFSET]
+ ldr r7, =0x0
+ ldr r8, =0x1000
+ str r7, [r11, r8]
+
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r4, [r11, #MX7D_GPC_IMR1]
+ ldr r5, [r11, #MX7D_GPC_IMR2]
+ ldr r6, [r11, #MX7D_GPC_IMR3]
+ ldr r7, [r11, #MX7D_GPC_IMR4]
+
+ ldr r8, =0xffffffff
+ str r8, [r11, #MX7D_GPC_IMR1]
+ str r8, [r11, #MX7D_GPC_IMR2]
+ str r8, [r11, #MX7D_GPC_IMR3]
+ str r8, [r11, #MX7D_GPC_IMR4]
+
+ /*
+ * enable the RBC bypass counter here
+ * to hold off the interrupts. RBC counter
+ * = 8 (240us). With this setting, the latency
+ * from wakeup interrupt to ARM power up
+ * is ~250uS.
+ */
+ ldr r8, [r11, #0x14]
+ bic r8, r8, #(0x3f << 24)
+ orr r8, r8, #(0x8 << 24)
+ str r8, [r11, #0x14]
+
+ /* enable the counter. */
+ ldr r8, [r11, #0x14]
+ orr r8, r8, #(0x1 << 30)
+ str r8, [r11, #0x14]
+
+ /* unmask all the GPC interrupts. */
+ str r4, [r11, #MX7D_GPC_IMR1]
+ str r5, [r11, #MX7D_GPC_IMR2]
+ str r6, [r11, #MX7D_GPC_IMR3]
+ str r7, [r11, #MX7D_GPC_IMR4]
+
+ /*
+ * now delay for a short while (3usec)
+ * ARM is at 1GHz at this point
+ * so a short loop should be enough.
+ * this delay is required to ensure that
+ * the RBC counter can start counting in
+ * case an interrupt is already pending
+ * or in case an interrupt arrives just
+ * as ARM is about to assert DSM_request.
+ */
+ ldr r7, =2000
+rbc_loop:
+ subs r7, r7, #0x1
+ bne rbc_loop
+wfi:
+ /* Zzz, enter stop mode */
+ wfi
+ nop
+ nop
+ nop
+ nop
+
+ mov r5, #0x0
+
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r7, [r11, #GPC_PGC_FM]
+ cmp r7, #0
+ beq wfi_ddr_self_refresh_out
+
+ ddr_exit_retention
+ b wfi_ddr_retention_out
+wfi_ddr_self_refresh_out:
+ ddrc_exit_self_refresh
+wfi_ddr_retention_out:
+
+ /* check whether it is a standby mode */
+ ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFFSET]
+ ldr r7, [r11, #GPC_PGC_C0]
+ cmp r7, #0
+ beq standby_out
+
+ ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFFSET]
+ ldr r7, =0x1
+ ldr r8, =0x1000
+ str r7, [r11, r8]
+
+ restore_ttbr1
+standby_out:
+ pop {r4-r12}
+ /* return to suspend finish */
+ mov pc, lr
+
+resume:
+ /* invalidate L1 I-cache first */
+ mov r6, #0x0
+ mcr p15, 0, r6, c7, c5, 0
+ mcr p15, 0, r6, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r6, #0x1800
+ mcr p15, 0, r6, c1, c0, 0
+ isb
+
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ /* clear core0's entry and parameter */
+ ldr r11, [r0, #PM_INFO_MX7_SRC_P_OFFSET]
+ mov r7, #0x0
+ str r7, [r11, #MX7_SRC_GPR1]
+ str r7, [r11, #MX7_SRC_GPR2]
+
+ mov r5, #0x1
+
+ ldr r11, [r0, #PM_INFO_MX7_GPC_P_OFFSET]
+ ldr r7, [r11, #GPC_PGC_FM]
+ cmp r7, #0
+ beq dsm_ddr_self_refresh_out
+
+ ddr_exit_retention
+ b dsm_ddr_retention_out
+dsm_ddr_self_refresh_out:
+ ddrc_exit_self_refresh
+dsm_ddr_retention_out:
+
+ mov pc, lr
+ENDPROC(imx7_suspend)
+
+ENTRY(ca7_cpu_resume)
+ bl v7_invalidate_l1
+ b cpu_resume
+ENDPROC(ca7_cpu_resume)
diff --git a/arch/arm/mach-imx/suspend-imx7ulp.S b/arch/arm/mach-imx/suspend-imx7ulp.S
new file mode 100644
index 000000000000..bd45e460f75f
--- /dev/null
+++ b/arch/arm/mach-imx/suspend-imx7ulp.S
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * 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/linkage.h>
+#include <asm/asm-offsets.h>
+#include "hardware.h"
+
+/*
+ * ==================== low level suspend ====================
+ *
+ * Better to follow below rules to use ARM registers:
+ * r0: pm_info structure address;
+ *
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ * .
+ * .
+ * .
+ * ^
+ * ^
+ * ^
+ * imx7ulp_suspend code
+ * PM_INFO structure(imx7ulp_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+/*
+ * Below offsets are based on struct imx7ulp_cpu_pm_info
+ * which defined in arch/arm/mach-imx/pm-imx7ulp.c, this
+ * structure contains necessary pm info for low level
+ * suspend related code.
+ */
+#define PM_INFO_M4_RESERVE0_OFFSET 0x0
+#define PM_INFO_M4_RESERVE1_OFFSET 0x4
+#define PM_INFO_M4_RESERVE2_OFFSET 0x8
+#define PM_INFO_PBASE_OFFSET 0xc
+#define PM_INFO_RESUME_ADDR_OFFSET 0x10
+#define PM_INFO_PM_INFO_SIZE_OFFSET 0x14
+#define PM_INFO_PM_INFO_SIM_VBASE_OFFSET 0x18
+#define PM_INFO_PM_INFO_SCG1_VBASE_OFFSET 0x1c
+#define PM_INFO_PM_INFO_MMDC_VBASE_OFFSET 0x20
+#define PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET 0x24
+#define PM_INFO_PM_INFO_SMC1_VBASE_OFFSET 0x28
+#define PM_INFO_PM_INFO_SCG1_VAL_OFFSET 0x2c
+#define PM_INFO_MX7ULP_TTBR1_V_OFFSET 0x70
+#define PM_INFO_MX7ULP_GPIO_REG_OFFSET 0x74
+#define PM_INFO_IOMUX_NUM_OFFSET 0x94
+#define PM_INFO_IOMUX_VAL_OFFSET 0x98
+#define PM_INFO_SELECT_INPUT_NUM_OFFSET 0x268
+#define PM_INFO_SELECT_INPUT_VAL_OFFSET 0x26c
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x3a4
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x3a8
+/* below offsets depends on MX7ULP_MAX_MMDC_IO_NUM(36) definition */
+#define PM_INFO_MMDC_NUM_OFFSET 0x5a8
+#define PM_INFO_MMDC_VAL_OFFSET 0x5ac
+
+#define DGO_CTRL0 0x50
+#define DGO_GPR3 0x60
+#define DGO_GPR4 0x64
+
+#define MX7ULP_MMDC_MISC 0x18
+#define MX7ULP_MMDC_MAPSR 0x404
+#define MX7ULP_MMDC_MPDGCTRL0 0x83c
+
+#define SCG_RCCR 0x14
+#define SCG_DDRCCR 0x30
+#define SCG_NICCCR 0x40
+#define SCG_FIRCDIV 0x304
+#define SCG_APLLCSR 0x500
+#define SCG_APLLDIV 0x504
+#define SCG_APLLCFG 0x508
+#define SCG_APLLPFD 0x50c
+#define SCG_APLLNUM 0x510
+#define SCG_APLLDENOM 0x514
+#define SCG_SPLLCSR 0x600
+#define SCG_SPLLDIV 0x604
+#define SCG_SPLLCFG 0x608
+#define SCG_SPLLPFD 0x60c
+#define SCG_SPLLNUM 0x610
+#define SCG_SPLLDENOM 0x614
+#define SCG_SOSCDIV 0x104
+
+#define PMC1_CTRL 0x24
+
+#define GPIO_PDOR 0x0
+#define GPIO_PDDR 0x14
+#define GPIO_PORT_NUM 0x4
+#define GPIO_PORT_OFFSET 0x40
+
+#define PMCTRL 0x10
+
+#define IOMUX_OFFSET 0x0
+#define SELECT_INPUT_OFFSET 0x200
+
+ .align 3
+
+ .macro store_ttbr1
+
+ /* Store TTBR1 to pm_info->ttbr1 */
+ mrc p15, 0, r7, c2, c0, 1
+ str r7, [r0, #PM_INFO_MX7ULP_TTBR1_V_OFFSET]
+
+ /* Disable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the BTAC. */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ ldr r6, =iram_tlb_phys_addr
+ ldr r6, [r6]
+ dsb
+ isb
+
+ /* Store the IRAM table in TTBR1 */
+ mcr p15, 0, r6, c2, c0, 1
+ /* Read TTBCR and set PD0=1, N = 1 */
+ mrc p15, 0, r6, c2, c0, 2
+ orr r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ .endm
+
+ .macro restore_ttbr1
+
+ /* Enable L1 data cache. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
+
+ dsb
+ isb
+
+ /* Restore TTBCR */
+ /* Read TTBCR and set PD0=0, N = 0 */
+ mrc p15, 0, r6, c2, c0, 2
+ bic r6, r6, #0x11
+ mcr p15, 0, r6, c2, c0, 2
+ dsb
+ isb
+
+ /* flush the TLB */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c8, c3, 0
+
+ /* Enable Branch Prediction, Z bit in SCTLR. */
+ mrc p15, 0, r6, c1, c0, 0
+ orr r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
+
+ /* Flush the Branch Target Address Cache (BTAC) */
+ ldr r6, =0x0
+ mcr p15, 0, r6, c7, c1, 6
+
+ /* Restore TTBR1, get the origin ttbr1 from pm info */
+ ldr r7, [r0, #PM_INFO_MX7ULP_TTBR1_V_OFFSET]
+ mcr p15, 0, r7, c2, c0, 1
+
+ .endm
+
+ .macro disable_l1_dcache
+
+ /*
+ * Flush all data from the L1 data cache before disabling
+ * SCTLR.C bit.
+ */
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ /* disable d-cache */
+ mrc p15, 0, r7, c1, c0, 0
+ bic r7, r7, #(1 << 2)
+ mcr p15, 0, r7, c1, c0, 0
+ dsb
+ isb
+
+ push {r0 - r10, lr}
+ ldr r7, =v7_flush_dcache_all
+ mov lr, pc
+ mov pc, r7
+ pop {r0 - r10, lr}
+
+ .endm
+
+ .macro restore_mmdc_settings
+
+ ldr r10, =MX7ULP_MMDC_IO_BASE_ADDR
+ ldr r11, =MX7ULP_MMDC_BASE_ADDR
+
+ /* resume mmdc iomuxc settings */
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+11:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r10, r8]
+ subs r6, r6, #0x1
+ bne 11b
+
+ /* restore MMDC settings */
+ ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_VAL_OFFSET
+ add r7, r7, r0
+1:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r11, r8]
+ subs r6, r6, #0x1
+ bne 1b
+
+ /* let DDR enter self-refresh */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ orr r7, r7, #(1 << 20)
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+2:
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ beq 2b
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ bic r7, r7, #(1 << 20)
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+3:
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ bne 3b
+
+ /* kick off MMDC */
+ ldr r4, =0x0
+ str r4, [r11, #0x1c]
+
+ /* let DDR out of self-refresh */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ bic r7, r7, #(1 << 20)
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+4:
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ bne 4b
+
+ /* enable DDR auto power saving */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+
+ .endm
+
+ENTRY(imx7ulp_suspend)
+ push {r4-r12}
+
+ /*
+ * The value of r0 is mapped the same in origin table and IRAM table,
+ * thus no need to care r0 here.
+ */
+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
+ ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+ ldr r3, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
+
+ /*
+ * counting the resume address in iram
+ * to set it in SRC register.
+ */
+ ldr r6, =imx7ulp_suspend
+ ldr r7, =resume
+ sub r7, r7, r6
+ add r8, r1, r3
+ add r9, r8, r7
+
+ ldr r11, [r0, #PM_INFO_PM_INFO_SIM_VBASE_OFFSET]
+ /* store physical resume addr and pm_info address. */
+ str r9, [r11, #DGO_GPR3]
+ str r1, [r11, #DGO_GPR4]
+ ldr r7, [r11, #DGO_CTRL0]
+ orr r7, r7, #0xc
+ str r7, [r11, #DGO_CTRL0]
+wait_dgo:
+ ldr r7, [r11, #DGO_CTRL0]
+ and r7, r7, #0x18000
+ cmp r7, #0x18000
+ bne wait_dgo
+
+ ldr r7, [r11, #DGO_CTRL0]
+ orr r7, r7, #0x18000
+ bic r7, r7, #0xc
+ str r7, [r11, #DGO_CTRL0]
+
+ disable_l1_dcache
+
+ store_ttbr1
+
+ ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_VBASE_OFFSET]
+
+ /*
+ * put DDR explicitly into self-refresh and
+ * disable automatic power savings.
+ */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ orr r7, r7, #0x1
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+
+ /* make the DDR explicitly enter self-refresh. */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ orr r7, r7, #(1 << 20)
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+
+poll_dvfs_set:
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ beq poll_dvfs_set
+
+ /* put mmdc io into lpm */
+ ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET]
+ ldr r10, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+mmdc_io_lpm:
+ ldr r8, [r7], #0x8
+ mov r9, #0x0
+ str r9, [r11, r8]
+ subs r10, r10, #0x1
+ bne mmdc_io_lpm
+
+ /* switch NIC clock to FIRC */
+ ldr r10, [r0, #PM_INFO_PM_INFO_SCG1_VBASE_OFFSET]
+ ldr r7, [r10, #SCG_NICCCR]
+ bic r7, #(1 << 28)
+ str r7, [r10, #SCG_NICCCR]
+
+ /* switch RUN clock to FIRC */
+ ldr r7, [r10, #SCG_RCCR]
+ bic r7, #(0xf << 24)
+ orr r7, #(0x3 << 24)
+ str r7, [r10, #SCG_RCCR]
+
+ /* turn off SPLL and SPFD */
+ ldr r7, [r10, #SCG_SPLLPFD]
+ mov r8, r7
+ orr r7, r7, #(0x1 << 31)
+ orr r7, r7, #(0x1 << 23)
+ orr r7, r7, #(0x1 << 15)
+ orr r7, r7, #(0x1 << 7)
+ str r7, [r10, #SCG_SPLLPFD]
+
+ ldr r7, [r10, #SCG_SPLLCSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #SCG_SPLLCSR]
+
+ /* turn off APLL and APFD */
+ ldr r7, [r10, #SCG_APLLPFD]
+ mov r9, r7
+ orr r7, r7, #(0x1 << 31)
+ orr r7, r7, #(0x1 << 23)
+ orr r7, r7, #(0x1 << 15)
+ orr r7, r7, #(0x1 << 7)
+ str r7, [r10, #SCG_APLLPFD]
+
+ ldr r7, [r10, #SCG_APLLCSR]
+ bic r7, r7, #0x1
+ str r7, [r10, #SCG_APLLCSR]
+
+ /* Zzz, enter stop mode */
+ wfi
+ nop
+ nop
+ nop
+ nop
+
+ /* clear core0's entry and parameter */
+ ldr r10, [r0, #PM_INFO_PM_INFO_SIM_VBASE_OFFSET]
+ mov r7, #0x0
+ str r7, [r10, #DGO_GPR3]
+ str r7, [r10, #DGO_GPR4]
+
+ /* enable SPLL and SPFD */
+ ldr r10, [r0, #PM_INFO_PM_INFO_SCG1_VBASE_OFFSET]
+ ldr r7, [r10, #SCG_SPLLCSR]
+ orr r7, r7, #1
+ str r7, [r10, #SCG_SPLLCSR]
+wait_spll:
+ ldr r7, [r10, #SCG_SPLLCSR]
+ ands r7, r7, #(1 << 24)
+ beq wait_spll
+
+ str r8, [r10, #SCG_SPLLPFD]
+ /* switch RUN clock to SPLL */
+ ldr r7, [r10, #SCG_RCCR]
+ bic r7, #(0xf << 24)
+ orr r7, #(0x6 << 24)
+ str r7, [r10, #SCG_RCCR]
+
+ /* enable APLL and APFD */
+ ldr r7, [r10, #SCG_APLLCSR]
+ orr r7, r7, #1
+ str r7, [r10, #SCG_APLLCSR]
+wait_apll:
+ ldr r7, [r10, #SCG_APLLCSR]
+ ands r7, r7, #(1 << 24)
+ beq wait_apll
+
+ str r9, [r10, #SCG_APLLPFD]
+
+ /* switch NIC clock to DDR */
+ ldr r7, [r10, #SCG_NICCCR]
+ orr r7, #(1 << 28)
+ str r7, [r10, #SCG_NICCCR]
+
+ /* let mmdc io out of lpm */
+ ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET]
+ ldr r10, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
+ add r7, r7, r0
+mmdc_io_exit_lpm:
+ ldr r8, [r7], #0x4
+ ldr r9, [r7], #0x4
+ str r9, [r11, r8]
+ subs r10, r10, #0x1
+ bne mmdc_io_exit_lpm
+
+ /* let DDR out of self-refresh */
+ ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_VBASE_OFFSET]
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ bic r7, r7, #(1 << 20)
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+poll_dvfs_clear:
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ ands r7, r7, #(1 << 24)
+ bne poll_dvfs_clear
+
+ /* enable DDR auto power saving */
+ ldr r7, [r11, #MX7ULP_MMDC_MAPSR]
+ bic r7, r7, #0x1
+ str r7, [r11, #MX7ULP_MMDC_MAPSR]
+
+ restore_ttbr1
+ pop {r4-r12}
+ /* return to suspend finish */
+ mov pc, lr
+
+resume:
+ /* invalidate L1 I-cache first */
+ mov r6, #0x0
+ mcr p15, 0, r6, c7, c5, 0
+ mcr p15, 0, r6, c7, c5, 6
+ /* enable the Icache and branch prediction */
+ mov r6, #0x1800
+ mcr p15, 0, r6, c1, c0, 0
+ isb
+
+ ldr r6, =MX7ULP_SIM_BASE_ADDR
+ ldr r0, [r6, #DGO_GPR4]
+ /* get physical resume address from pm_info. */
+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
+
+ ldr r11, =MX7ULP_SCG1_BASE_ADDR
+ /* enable spll and pfd0 */
+ ldr r5, =PM_INFO_PM_INFO_SCG1_VAL_OFFSET
+ add r6, r5, #48
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLCFG]
+
+ add r6, r5, #56
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLNUM]
+
+ add r6, r5, #60
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLDENOM]
+
+ add r6, r5, #40
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLCSR]
+5:
+ ldr r7, [r11, #SCG_SPLLCSR]
+ ands r7, r7, #0x1000000
+ beq 5b
+
+ add r6, r5, #44
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLDIV]
+
+ add r6, r5, #52
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SPLLPFD]
+
+ add r6, r5, #0
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_RCCR]
+
+ /* enable apll and pfd0 */
+ add r6, r5, #24
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLCFG]
+
+ add r6, r5, #32
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLNUM]
+
+ add r6, r5, #36
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLDENOM]
+
+ add r6, r5, #16
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLCSR]
+6:
+ ldr r7, [r11, #SCG_APLLCSR]
+ ands r7, r7, #0x1000000
+ beq 6b
+
+ add r6, r5, #20
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLDIV]
+
+ add r6, r5, #28
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_APLLPFD]
+
+ /* set ddr ccr */
+ add r6, r5, #4
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_DDRCCR]
+
+ /* set nic sel */
+ add r6, r5, #8
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_NICCCR]
+
+ /* set firc div2 to get 48MHz */
+ add r6, r5, #12
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_FIRCDIV]
+
+ /* restore system OSC div */
+ add r6, r5, #64
+ ldr r7, [r0, r6]
+ str r7, [r11, #SCG_SOSCDIV]
+
+ /* enable mmdc clock in pcc3 */
+ ldr r11, =MX7ULP_PCC3_BASE_ADDR
+ ldr r7, [r11, #0xac]
+ orr r7, r7, #(1 << 30)
+ str r7, [r11, #0xac]
+
+ /* enable GPIO clock in pcc2 */
+ ldr r11, =MX7ULP_PCC2_BASE_ADDR
+ ldr r7, [r11, #0x3c]
+ orr r7, r7, #(1 << 30)
+ str r7, [r11, #0x3c]
+
+ /* restore gpio settings */
+ ldr r10, =MX7ULP_GPIOC_BASE_ADDR
+ ldr r7, =PM_INFO_MX7ULP_GPIO_REG_OFFSET
+ add r7, r7, r0
+ ldr r6, =GPIO_PORT_NUM
+12:
+ ldr r9, [r7], #0x4
+ str r9, [r10, #GPIO_PDOR]
+ ldr r9, [r7], #0x4
+ str r9, [r10, #GPIO_PDDR]
+ add r10, r10, #GPIO_PORT_OFFSET
+ subs r6, r6, #0x1
+ bne 12b
+
+ /* restore iomuxc settings */
+ ldr r10, =MX7ULP_IOMUXC1_BASE_ADDR
+ add r10, r10, #IOMUX_OFFSET
+ ldr r6, [r0, #PM_INFO_IOMUX_NUM_OFFSET]
+ ldr r7, =PM_INFO_IOMUX_VAL_OFFSET
+ add r7, r7, r0
+13:
+ ldr r9, [r7], #0x4
+ str r9, [r10], #0x4
+ subs r6, r6, #0x1
+ bne 13b
+
+ /* restore select input settings */
+ ldr r10, =MX7ULP_IOMUXC1_BASE_ADDR
+ add r10, r10, #SELECT_INPUT_OFFSET
+ ldr r6, [r0, #PM_INFO_SELECT_INPUT_NUM_OFFSET]
+ ldr r7, =PM_INFO_SELECT_INPUT_VAL_OFFSET
+ add r7, r7, r0
+14:
+ ldr r9, [r7], #0x4
+ str r9, [r10], #0x4
+ subs r6, r6, #0x1
+ bne 14b
+
+ /* isoack */
+ ldr r6, =MX7ULP_PMC1_BASE_ADDR
+ ldr r7, [r6, #PMC1_CTRL]
+ orr r7, r7, #(1 << 14)
+ str r7, [r6, #PMC1_CTRL]
+
+ restore_mmdc_settings
+
+ mov pc, lr
+ENDPROC(imx7ulp_suspend)
+
+ENTRY(imx7ulp_cpu_resume)
+ bl v7_invalidate_l1
+ b cpu_resume
+ENDPROC(imx7ulp_cpu_resume)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 27576c7b836e..15c8733ce44a 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2320,6 +2320,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
#endif
dev->archdata.dma_ops_setup = true;
}
+EXPORT_SYMBOL(arch_setup_dma_ops);
void arch_teardown_dma_ops(struct device *dev)
{
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index d42b93316183..5606c0e7fde4 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -399,6 +399,13 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
}
EXPORT_SYMBOL(ioremap_wc);
+void __iomem *ioremap_cache_ns(resource_size_t res_cookie, size_t size)
+{
+ return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RW_NS,
+ __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_cache_ns);
+
/*
* Remap an arbitrary physical address space into the kernel virtual
* address space as memory. Needed when the kernel wants to execute
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 48c2888297dd..5cf31b491382 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -312,6 +312,13 @@ static struct mem_type mem_types[] __ro_after_init = {
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
.domain = DOMAIN_KERNEL,
},
+ [MT_MEMORY_RW_NS] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_XN,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_XN,
+ .domain = DOMAIN_KERNEL,
+ },
[MT_ROM] = {
.prot_sect = PMD_TYPE_SECT,
.domain = DOMAIN_KERNEL,
@@ -648,6 +655,7 @@ static void __init build_mem_type_table(void)
}
kern_pgprot |= PTE_EXT_AF;
vecs_pgprot |= PTE_EXT_AF;
+ mem_types[MT_MEMORY_RW_NS].prot_pte |= PTE_EXT_AF | cp->pte;
/*
* Set PXN for user mappings
@@ -676,6 +684,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot;
mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd;
mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot;
+ mem_types[MT_MEMORY_RW_NS].prot_sect |= ecc_mask | cp->pmd;
mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask;
mem_types[MT_ROM].prot_sect |= cp->pmd;